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/BitVector.h" 19 #include "llvm/ADT/DenseMap.h" 20 #include "llvm/ADT/DenseSet.h" 21 #include "llvm/ADT/Hashing.h" 22 #include "llvm/ADT/StringRef.h" 23 #include "llvm/ADT/iterator.h" 24 #include "llvm/ADT/iterator_range.h" 25 #include "llvm/Object/BuildID.h" 26 #include "llvm/ProfileData/Coverage/MCDCTypes.h" 27 #include "llvm/ProfileData/InstrProf.h" 28 #include "llvm/Support/Alignment.h" 29 #include "llvm/Support/Compiler.h" 30 #include "llvm/Support/Debug.h" 31 #include "llvm/Support/Endian.h" 32 #include "llvm/Support/Error.h" 33 #include "llvm/Support/raw_ostream.h" 34 #include <cassert> 35 #include <cstdint> 36 #include <iterator> 37 #include <memory> 38 #include <sstream> 39 #include <string> 40 #include <system_error> 41 #include <utility> 42 #include <vector> 43 44 namespace llvm { 45 46 class IndexedInstrProfReader; 47 48 namespace object { 49 class BuildIDFetcher; 50 } // namespace object 51 52 namespace vfs { 53 class FileSystem; 54 } // namespace vfs 55 56 namespace coverage { 57 58 class CoverageMappingReader; 59 struct CoverageMappingRecord; 60 61 enum class coveragemap_error { 62 success = 0, 63 eof, 64 no_data_found, 65 unsupported_version, 66 truncated, 67 malformed, 68 decompression_failed, 69 invalid_or_missing_arch_specifier 70 }; 71 72 const std::error_category &coveragemap_category(); 73 74 inline std::error_code make_error_code(coveragemap_error E) { 75 return std::error_code(static_cast<int>(E), coveragemap_category()); 76 } 77 78 class CoverageMapError : public ErrorInfo<CoverageMapError> { 79 public: 80 CoverageMapError(coveragemap_error Err, const Twine &ErrStr = Twine()) 81 : Err(Err), Msg(ErrStr.str()) { 82 assert(Err != coveragemap_error::success && "Not an error"); 83 } 84 85 std::string message() const override; 86 87 void log(raw_ostream &OS) const override { OS << message(); } 88 89 std::error_code convertToErrorCode() const override { 90 return make_error_code(Err); 91 } 92 93 coveragemap_error get() const { return Err; } 94 const std::string &getMessage() const { return Msg; } 95 96 static char ID; 97 98 private: 99 coveragemap_error Err; 100 std::string Msg; 101 }; 102 103 /// A Counter is an abstract value that describes how to compute the 104 /// execution count for a region of code using the collected profile count data. 105 struct Counter { 106 /// The CounterExpression kind (Add or Subtract) is encoded in bit 0 next to 107 /// the CounterKind. This means CounterKind has to leave bit 0 free. 108 enum CounterKind { Zero, CounterValueReference, Expression }; 109 static const unsigned EncodingTagBits = 2; 110 static const unsigned EncodingTagMask = 0x3; 111 static const unsigned EncodingCounterTagAndExpansionRegionTagBits = 112 EncodingTagBits + 1; 113 114 private: 115 CounterKind Kind = Zero; 116 unsigned ID = 0; 117 118 Counter(CounterKind Kind, unsigned ID) : Kind(Kind), ID(ID) {} 119 120 public: 121 Counter() = default; 122 123 CounterKind getKind() const { return Kind; } 124 125 bool isZero() const { return Kind == Zero; } 126 127 bool isExpression() const { return Kind == Expression; } 128 129 unsigned getCounterID() const { return ID; } 130 131 unsigned getExpressionID() const { return ID; } 132 133 friend bool operator==(const Counter &LHS, const Counter &RHS) { 134 return LHS.Kind == RHS.Kind && LHS.ID == RHS.ID; 135 } 136 137 friend bool operator!=(const Counter &LHS, const Counter &RHS) { 138 return !(LHS == RHS); 139 } 140 141 friend bool operator<(const Counter &LHS, const Counter &RHS) { 142 return std::tie(LHS.Kind, LHS.ID) < std::tie(RHS.Kind, RHS.ID); 143 } 144 145 /// Return the counter that represents the number zero. 146 static Counter getZero() { return Counter(); } 147 148 /// Return the counter that corresponds to a specific profile counter. 149 static Counter getCounter(unsigned CounterId) { 150 return Counter(CounterValueReference, CounterId); 151 } 152 153 /// Return the counter that corresponds to a specific addition counter 154 /// expression. 155 static Counter getExpression(unsigned ExpressionId) { 156 return Counter(Expression, ExpressionId); 157 } 158 }; 159 160 /// A Counter expression is a value that represents an arithmetic operation 161 /// with two counters. 162 struct CounterExpression { 163 enum ExprKind { Subtract, Add }; 164 ExprKind Kind; 165 Counter LHS, RHS; 166 167 CounterExpression(ExprKind Kind, Counter LHS, Counter RHS) 168 : Kind(Kind), LHS(LHS), RHS(RHS) {} 169 }; 170 171 /// A Counter expression builder is used to construct the counter expressions. 172 /// It avoids unnecessary duplication and simplifies algebraic expressions. 173 class CounterExpressionBuilder { 174 /// A list of all the counter expressions 175 std::vector<CounterExpression> Expressions; 176 177 /// A lookup table for the index of a given expression. 178 DenseMap<CounterExpression, unsigned> ExpressionIndices; 179 180 /// Return the counter which corresponds to the given expression. 181 /// 182 /// If the given expression is already stored in the builder, a counter 183 /// that references that expression is returned. Otherwise, the given 184 /// expression is added to the builder's collection of expressions. 185 Counter get(const CounterExpression &E); 186 187 /// Represents a term in a counter expression tree. 188 struct Term { 189 unsigned CounterID; 190 int Factor; 191 192 Term(unsigned CounterID, int Factor) 193 : CounterID(CounterID), Factor(Factor) {} 194 }; 195 196 /// Gather the terms of the expression tree for processing. 197 /// 198 /// This collects each addition and subtraction referenced by the counter into 199 /// a sequence that can be sorted and combined to build a simplified counter 200 /// expression. 201 void extractTerms(Counter C, int Sign, SmallVectorImpl<Term> &Terms); 202 203 /// Simplifies the given expression tree 204 /// by getting rid of algebraically redundant operations. 205 Counter simplify(Counter ExpressionTree); 206 207 public: 208 ArrayRef<CounterExpression> getExpressions() const { return Expressions; } 209 210 /// Return a counter that represents the expression that adds LHS and RHS. 211 Counter add(Counter LHS, Counter RHS, bool Simplify = true); 212 213 /// Return a counter that represents the expression that subtracts RHS from 214 /// LHS. 215 Counter subtract(Counter LHS, Counter RHS, bool Simplify = true); 216 }; 217 218 using LineColPair = std::pair<unsigned, unsigned>; 219 220 /// A Counter mapping region associates a source range with a specific counter. 221 struct CounterMappingRegion { 222 enum RegionKind { 223 /// A CodeRegion associates some code with a counter 224 CodeRegion, 225 226 /// An ExpansionRegion represents a file expansion region that associates 227 /// a source range with the expansion of a virtual source file, such as 228 /// for a macro instantiation or #include file. 229 ExpansionRegion, 230 231 /// A SkippedRegion represents a source range with code that was skipped 232 /// by a preprocessor or similar means. 233 SkippedRegion, 234 235 /// A GapRegion is like a CodeRegion, but its count is only set as the 236 /// line execution count when its the only region in the line. 237 GapRegion, 238 239 /// A BranchRegion represents leaf-level boolean expressions and is 240 /// associated with two counters, each representing the number of times the 241 /// expression evaluates to true or false. 242 BranchRegion, 243 244 /// A DecisionRegion represents a top-level boolean expression and is 245 /// associated with a variable length bitmap index and condition number. 246 MCDCDecisionRegion, 247 248 /// A Branch Region can be extended to include IDs to facilitate MC/DC. 249 MCDCBranchRegion 250 }; 251 252 /// Primary Counter that is also used for Branch Regions (TrueCount). 253 Counter Count; 254 255 /// Secondary Counter used for Branch Regions (FalseCount). 256 Counter FalseCount; 257 258 /// Parameters used for Modified Condition/Decision Coverage 259 mcdc::Parameters MCDCParams; 260 261 const auto &getDecisionParams() const { 262 return mcdc::getParams<const mcdc::DecisionParameters>(MCDCParams); 263 } 264 265 const auto &getBranchParams() const { 266 return mcdc::getParams<const mcdc::BranchParameters>(MCDCParams); 267 } 268 269 unsigned FileID = 0; 270 unsigned ExpandedFileID = 0; 271 unsigned LineStart, ColumnStart, LineEnd, ColumnEnd; 272 273 RegionKind Kind; 274 275 CounterMappingRegion(Counter Count, unsigned FileID, unsigned ExpandedFileID, 276 unsigned LineStart, unsigned ColumnStart, 277 unsigned LineEnd, unsigned ColumnEnd, RegionKind Kind) 278 : Count(Count), FileID(FileID), ExpandedFileID(ExpandedFileID), 279 LineStart(LineStart), ColumnStart(ColumnStart), LineEnd(LineEnd), 280 ColumnEnd(ColumnEnd), Kind(Kind) {} 281 282 CounterMappingRegion(Counter Count, Counter FalseCount, unsigned FileID, 283 unsigned ExpandedFileID, unsigned LineStart, 284 unsigned ColumnStart, unsigned LineEnd, 285 unsigned ColumnEnd, RegionKind Kind, 286 const mcdc::Parameters &MCDCParams = std::monostate()) 287 : Count(Count), FalseCount(FalseCount), MCDCParams(MCDCParams), 288 FileID(FileID), ExpandedFileID(ExpandedFileID), LineStart(LineStart), 289 ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), 290 Kind(Kind) {} 291 292 CounterMappingRegion(const mcdc::DecisionParameters &MCDCParams, 293 unsigned FileID, unsigned LineStart, 294 unsigned ColumnStart, unsigned LineEnd, 295 unsigned ColumnEnd, RegionKind Kind) 296 : MCDCParams(MCDCParams), FileID(FileID), LineStart(LineStart), 297 ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd), 298 Kind(Kind) {} 299 300 static CounterMappingRegion 301 makeRegion(Counter Count, unsigned FileID, unsigned LineStart, 302 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 303 return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 304 LineEnd, ColumnEnd, CodeRegion); 305 } 306 307 static CounterMappingRegion 308 makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart, 309 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 310 return CounterMappingRegion(Counter(), FileID, ExpandedFileID, LineStart, 311 ColumnStart, LineEnd, ColumnEnd, 312 ExpansionRegion); 313 } 314 315 static CounterMappingRegion 316 makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart, 317 unsigned LineEnd, unsigned ColumnEnd) { 318 return CounterMappingRegion(Counter(), FileID, 0, LineStart, ColumnStart, 319 LineEnd, ColumnEnd, SkippedRegion); 320 } 321 322 static CounterMappingRegion 323 makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart, 324 unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) { 325 return CounterMappingRegion(Count, FileID, 0, LineStart, ColumnStart, 326 LineEnd, (1U << 31) | ColumnEnd, GapRegion); 327 } 328 329 static CounterMappingRegion 330 makeBranchRegion(Counter Count, Counter FalseCount, unsigned FileID, 331 unsigned LineStart, unsigned ColumnStart, unsigned LineEnd, 332 unsigned ColumnEnd, 333 const mcdc::Parameters &MCDCParams = std::monostate()) { 334 return CounterMappingRegion( 335 Count, FalseCount, FileID, 0, LineStart, ColumnStart, LineEnd, 336 ColumnEnd, 337 (std::get_if<mcdc::BranchParameters>(&MCDCParams) ? MCDCBranchRegion 338 : BranchRegion), 339 MCDCParams); 340 } 341 342 static CounterMappingRegion 343 makeDecisionRegion(const mcdc::DecisionParameters &MCDCParams, 344 unsigned FileID, unsigned LineStart, unsigned ColumnStart, 345 unsigned LineEnd, unsigned ColumnEnd) { 346 return CounterMappingRegion(MCDCParams, FileID, LineStart, ColumnStart, 347 LineEnd, ColumnEnd, MCDCDecisionRegion); 348 } 349 350 inline LineColPair startLoc() const { 351 return LineColPair(LineStart, ColumnStart); 352 } 353 354 inline LineColPair endLoc() const { return LineColPair(LineEnd, ColumnEnd); } 355 }; 356 357 /// Associates a source range with an execution count. 358 struct CountedRegion : public CounterMappingRegion { 359 uint64_t ExecutionCount; 360 uint64_t FalseExecutionCount; 361 bool Folded; 362 bool HasSingleByteCoverage; 363 364 CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, 365 bool HasSingleByteCoverage) 366 : CounterMappingRegion(R), ExecutionCount(ExecutionCount), 367 FalseExecutionCount(0), Folded(false), 368 HasSingleByteCoverage(HasSingleByteCoverage) {} 369 370 CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount, 371 uint64_t FalseExecutionCount, bool HasSingleByteCoverage) 372 : CounterMappingRegion(R), ExecutionCount(ExecutionCount), 373 FalseExecutionCount(FalseExecutionCount), Folded(false), 374 HasSingleByteCoverage(HasSingleByteCoverage) {} 375 }; 376 377 /// MCDC Record grouping all information together. 378 struct MCDCRecord { 379 /// CondState represents the evaluation of a condition in an executed test 380 /// vector, which can be True or False. A DontCare is used to mask an 381 /// unevaluatable condition resulting from short-circuit behavior of logical 382 /// operators in languages like C/C++. When comparing the evaluation of a 383 /// condition across executed test vectors, comparisons against a DontCare 384 /// are effectively ignored. 385 enum CondState { MCDC_DontCare = -1, MCDC_False = 0, MCDC_True = 1 }; 386 387 /// Emulate SmallVector<CondState> with a pair of BitVector. 388 /// 389 /// True False DontCare (Impossible) 390 /// Values: True False False True 391 /// Visited: True True False False 392 class TestVector { 393 BitVector Values; /// True/False (False when DontCare) 394 BitVector Visited; /// ~DontCare 395 396 public: 397 /// Default values are filled with DontCare. 398 TestVector(unsigned N) : Values(N), Visited(N) {} 399 400 /// Emulate RHS SmallVector::operator[] 401 CondState operator[](int I) const { 402 return (Visited[I] ? (Values[I] ? MCDC_True : MCDC_False) 403 : MCDC_DontCare); 404 } 405 406 /// Equivalent to buildTestVector's Index. 407 auto getIndex() const { return Values.getData()[0]; } 408 409 /// Set the condition \p Val at position \p I. 410 /// This emulates LHS SmallVector::operator[]. 411 void set(int I, CondState Val) { 412 Visited[I] = (Val != MCDC_DontCare); 413 Values[I] = (Val == MCDC_True); 414 } 415 416 /// Emulate SmallVector::push_back. 417 void push_back(CondState Val) { 418 Visited.push_back(Val != MCDC_DontCare); 419 Values.push_back(Val == MCDC_True); 420 assert(Values.size() == Visited.size()); 421 } 422 423 /// For each element: 424 /// - False if either is DontCare 425 /// - False if both have the same value 426 /// - True if both have the opposite value 427 /// ((A.Values ^ B.Values) & A.Visited & B.Visited) 428 /// Dedicated to findIndependencePairs(). 429 auto getDifferences(const TestVector &B) const { 430 const auto &A = *this; 431 BitVector AB = A.Values; 432 AB ^= B.Values; 433 AB &= A.Visited; 434 AB &= B.Visited; 435 return AB; 436 } 437 }; 438 439 using TestVectors = llvm::SmallVector<std::pair<TestVector, CondState>>; 440 using BoolVector = llvm::SmallVector<bool>; 441 using TVRowPair = std::pair<unsigned, unsigned>; 442 using TVPairMap = llvm::DenseMap<unsigned, TVRowPair>; 443 using CondIDMap = llvm::DenseMap<unsigned, unsigned>; 444 using LineColPairMap = llvm::DenseMap<unsigned, LineColPair>; 445 446 private: 447 CounterMappingRegion Region; 448 TestVectors TV; 449 TVPairMap IndependencePairs; 450 BoolVector Folded; 451 CondIDMap PosToID; 452 LineColPairMap CondLoc; 453 454 public: 455 MCDCRecord(const CounterMappingRegion &Region, TestVectors &&TV, 456 TVPairMap &&IndependencePairs, BoolVector &&Folded, 457 CondIDMap &&PosToID, LineColPairMap &&CondLoc) 458 : Region(Region), TV(std::move(TV)), 459 IndependencePairs(std::move(IndependencePairs)), 460 Folded(std::move(Folded)), PosToID(std::move(PosToID)), 461 CondLoc(std::move(CondLoc)){}; 462 463 CounterMappingRegion getDecisionRegion() const { return Region; } 464 unsigned getNumConditions() const { 465 return Region.getDecisionParams().NumConditions; 466 } 467 unsigned getNumTestVectors() const { return TV.size(); } 468 bool isCondFolded(unsigned Condition) const { return Folded[Condition]; } 469 470 /// Return the evaluation of a condition (indicated by Condition) in an 471 /// executed test vector (indicated by TestVectorIndex), which will be True, 472 /// False, or DontCare if the condition is unevaluatable. Because condition 473 /// IDs are not associated based on their position in the expression, 474 /// accessing conditions in the TestVectors requires a translation from a 475 /// ordinal position to actual condition ID. This is done via PosToID[]. 476 CondState getTVCondition(unsigned TestVectorIndex, unsigned Condition) { 477 return TV[TestVectorIndex].first[PosToID[Condition]]; 478 } 479 480 /// Return the Result evaluation for an executed test vector. 481 /// See MCDCRecordProcessor::RecordTestVector(). 482 CondState getTVResult(unsigned TestVectorIndex) { 483 return TV[TestVectorIndex].second; 484 } 485 486 /// Determine whether a given condition (indicated by Condition) is covered 487 /// by an Independence Pair. Because condition IDs are not associated based 488 /// on their position in the expression, accessing conditions in the 489 /// TestVectors requires a translation from a ordinal position to actual 490 /// condition ID. This is done via PosToID[]. 491 bool isConditionIndependencePairCovered(unsigned Condition) const { 492 auto It = PosToID.find(Condition); 493 if (It != PosToID.end()) 494 return IndependencePairs.contains(It->second); 495 llvm_unreachable("Condition ID without an Ordinal mapping"); 496 } 497 498 /// Return the Independence Pair that covers the given condition. Because 499 /// condition IDs are not associated based on their position in the 500 /// expression, accessing conditions in the TestVectors requires a 501 /// translation from a ordinal position to actual condition ID. This is done 502 /// via PosToID[]. 503 TVRowPair getConditionIndependencePair(unsigned Condition) { 504 assert(isConditionIndependencePairCovered(Condition)); 505 return IndependencePairs[PosToID[Condition]]; 506 } 507 508 float getPercentCovered() const { 509 unsigned Folded = 0; 510 unsigned Covered = 0; 511 for (unsigned C = 0; C < getNumConditions(); C++) { 512 if (isCondFolded(C)) 513 Folded++; 514 else if (isConditionIndependencePairCovered(C)) 515 Covered++; 516 } 517 518 unsigned Total = getNumConditions() - Folded; 519 if (Total == 0) 520 return 0.0; 521 return (static_cast<double>(Covered) / static_cast<double>(Total)) * 100.0; 522 } 523 524 std::string getConditionHeaderString(unsigned Condition) { 525 std::ostringstream OS; 526 OS << "Condition C" << Condition + 1 << " --> ("; 527 OS << CondLoc[Condition].first << ":" << CondLoc[Condition].second; 528 OS << ")\n"; 529 return OS.str(); 530 } 531 532 std::string getTestVectorHeaderString() const { 533 std::ostringstream OS; 534 if (getNumTestVectors() == 0) { 535 OS << "None.\n"; 536 return OS.str(); 537 } 538 const auto NumConditions = getNumConditions(); 539 for (unsigned I = 0; I < NumConditions; I++) { 540 OS << "C" << I + 1; 541 if (I != NumConditions - 1) 542 OS << ", "; 543 } 544 OS << " Result\n"; 545 return OS.str(); 546 } 547 548 std::string getTestVectorString(unsigned TestVectorIndex) { 549 assert(TestVectorIndex < getNumTestVectors() && 550 "TestVector index out of bounds!"); 551 std::ostringstream OS; 552 const auto NumConditions = getNumConditions(); 553 // Add individual condition values to the string. 554 OS << " " << TestVectorIndex + 1 << " { "; 555 for (unsigned Condition = 0; Condition < NumConditions; Condition++) { 556 if (isCondFolded(Condition)) 557 OS << "C"; 558 else { 559 switch (getTVCondition(TestVectorIndex, Condition)) { 560 case MCDCRecord::MCDC_DontCare: 561 OS << "-"; 562 break; 563 case MCDCRecord::MCDC_True: 564 OS << "T"; 565 break; 566 case MCDCRecord::MCDC_False: 567 OS << "F"; 568 break; 569 } 570 } 571 if (Condition != NumConditions - 1) 572 OS << ", "; 573 } 574 575 // Add result value to the string. 576 OS << " = "; 577 if (getTVResult(TestVectorIndex) == MCDC_True) 578 OS << "T"; 579 else 580 OS << "F"; 581 OS << " }\n"; 582 583 return OS.str(); 584 } 585 586 std::string getConditionCoverageString(unsigned Condition) { 587 assert(Condition < getNumConditions() && 588 "Condition index is out of bounds!"); 589 std::ostringstream OS; 590 591 OS << " C" << Condition + 1 << "-Pair: "; 592 if (isCondFolded(Condition)) { 593 OS << "constant folded\n"; 594 } else if (isConditionIndependencePairCovered(Condition)) { 595 TVRowPair rows = getConditionIndependencePair(Condition); 596 OS << "covered: (" << rows.first << ","; 597 OS << rows.second << ")\n"; 598 } else 599 OS << "not covered\n"; 600 601 return OS.str(); 602 } 603 }; 604 605 namespace mcdc { 606 /// Compute TestVector Indices "TVIdx" from the Conds graph. 607 /// 608 /// Clang CodeGen handles the bitmap index based on TVIdx. 609 /// llvm-cov reconstructs conditions from TVIdx. 610 /// 611 /// For each leaf "The final decision", 612 /// - TVIdx should be unique. 613 /// - TVIdx has the Width. 614 /// - The width represents the number of possible paths. 615 /// - The minimum width is 1 "deterministic". 616 /// - The order of leaves are sorted by Width DESC. It expects 617 /// latter TVIdx(s) (with Width=1) could be pruned and altered to 618 /// other simple branch conditions. 619 /// 620 class TVIdxBuilder { 621 public: 622 struct MCDCNode { 623 int InCount = 0; /// Reference count; temporary use 624 int Width; /// Number of accumulated paths (>= 1) 625 ConditionIDs NextIDs; 626 }; 627 628 #ifndef NDEBUG 629 /// This is no longer needed after the assignment. 630 /// It may be used in assert() for reconfirmation. 631 SmallVector<MCDCNode> SavedNodes; 632 #endif 633 634 /// Output: Index for TestVectors bitmap (These are not CondIDs) 635 SmallVector<std::array<int, 2>> Indices; 636 637 /// Output: The number of test vectors. 638 /// Error with HardMaxTVs if the number has exploded. 639 int NumTestVectors; 640 641 /// Hard limit of test vectors 642 static constexpr auto HardMaxTVs = 643 std::numeric_limits<decltype(NumTestVectors)>::max(); 644 645 public: 646 /// Calculate and assign Indices 647 /// \param NextIDs The list of {FalseID, TrueID} indexed by ID 648 /// The first element [0] should be the root node. 649 /// \param Offset Offset of index to final decisions. 650 TVIdxBuilder(const SmallVectorImpl<ConditionIDs> &NextIDs, int Offset = 0); 651 }; 652 } // namespace mcdc 653 654 /// A Counter mapping context is used to connect the counters, expressions 655 /// and the obtained counter values. 656 class CounterMappingContext { 657 ArrayRef<CounterExpression> Expressions; 658 ArrayRef<uint64_t> CounterValues; 659 BitVector Bitmap; 660 661 public: 662 CounterMappingContext(ArrayRef<CounterExpression> Expressions, 663 ArrayRef<uint64_t> CounterValues = std::nullopt) 664 : Expressions(Expressions), CounterValues(CounterValues) {} 665 666 void setCounts(ArrayRef<uint64_t> Counts) { CounterValues = Counts; } 667 void setBitmap(BitVector &&Bitmap_) { Bitmap = std::move(Bitmap_); } 668 669 void dump(const Counter &C, raw_ostream &OS) const; 670 void dump(const Counter &C) const { dump(C, dbgs()); } 671 672 /// Return the number of times that a region of code associated with this 673 /// counter was executed. 674 Expected<int64_t> evaluate(const Counter &C) const; 675 676 /// Return an MCDC record that indicates executed test vectors and condition 677 /// pairs. 678 Expected<MCDCRecord> 679 evaluateMCDCRegion(const CounterMappingRegion &Region, 680 ArrayRef<const CounterMappingRegion *> Branches, 681 bool IsVersion11); 682 683 unsigned getMaxCounterID(const Counter &C) const; 684 }; 685 686 /// Code coverage information for a single function. 687 struct FunctionRecord { 688 /// Raw function name. 689 std::string Name; 690 /// Mapping from FileID (i.e. vector index) to filename. Used to support 691 /// macro expansions within a function in which the macro and function are 692 /// defined in separate files. 693 /// 694 /// TODO: Uniquing filenames across all function records may be a performance 695 /// optimization. 696 std::vector<std::string> Filenames; 697 /// Regions in the function along with their counts. 698 std::vector<CountedRegion> CountedRegions; 699 /// Branch Regions in the function along with their counts. 700 std::vector<CountedRegion> CountedBranchRegions; 701 /// MCDC Records record a DecisionRegion and associated BranchRegions. 702 std::vector<MCDCRecord> MCDCRecords; 703 /// The number of times this function was executed. 704 uint64_t ExecutionCount = 0; 705 706 FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames) 707 : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {} 708 709 FunctionRecord(FunctionRecord &&FR) = default; 710 FunctionRecord &operator=(FunctionRecord &&) = default; 711 712 void pushMCDCRecord(MCDCRecord &&Record) { 713 MCDCRecords.push_back(std::move(Record)); 714 } 715 716 void pushRegion(CounterMappingRegion Region, uint64_t Count, 717 uint64_t FalseCount, bool HasSingleByteCoverage) { 718 if (Region.Kind == CounterMappingRegion::BranchRegion || 719 Region.Kind == CounterMappingRegion::MCDCBranchRegion) { 720 CountedBranchRegions.emplace_back(Region, Count, FalseCount, 721 HasSingleByteCoverage); 722 // If both counters are hard-coded to zero, then this region represents a 723 // constant-folded branch. 724 if (Region.Count.isZero() && Region.FalseCount.isZero()) 725 CountedBranchRegions.back().Folded = true; 726 return; 727 } 728 if (CountedRegions.empty()) 729 ExecutionCount = Count; 730 CountedRegions.emplace_back(Region, Count, FalseCount, 731 HasSingleByteCoverage); 732 } 733 }; 734 735 /// Iterator over Functions, optionally filtered to a single file. 736 class FunctionRecordIterator 737 : public iterator_facade_base<FunctionRecordIterator, 738 std::forward_iterator_tag, FunctionRecord> { 739 ArrayRef<FunctionRecord> Records; 740 ArrayRef<FunctionRecord>::iterator Current; 741 StringRef Filename; 742 743 /// Skip records whose primary file is not \c Filename. 744 void skipOtherFiles(); 745 746 public: 747 FunctionRecordIterator(ArrayRef<FunctionRecord> Records_, 748 StringRef Filename = "") 749 : Records(Records_), Current(Records.begin()), Filename(Filename) { 750 skipOtherFiles(); 751 } 752 753 FunctionRecordIterator() : Current(Records.begin()) {} 754 755 bool operator==(const FunctionRecordIterator &RHS) const { 756 return Current == RHS.Current && Filename == RHS.Filename; 757 } 758 759 const FunctionRecord &operator*() const { return *Current; } 760 761 FunctionRecordIterator &operator++() { 762 assert(Current != Records.end() && "incremented past end"); 763 ++Current; 764 skipOtherFiles(); 765 return *this; 766 } 767 }; 768 769 /// Coverage information for a macro expansion or #included file. 770 /// 771 /// When covered code has pieces that can be expanded for more detail, such as a 772 /// preprocessor macro use and its definition, these are represented as 773 /// expansions whose coverage can be looked up independently. 774 struct ExpansionRecord { 775 /// The abstract file this expansion covers. 776 unsigned FileID; 777 /// The region that expands to this record. 778 const CountedRegion &Region; 779 /// Coverage for the expansion. 780 const FunctionRecord &Function; 781 782 ExpansionRecord(const CountedRegion &Region, 783 const FunctionRecord &Function) 784 : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {} 785 }; 786 787 /// The execution count information starting at a point in a file. 788 /// 789 /// A sequence of CoverageSegments gives execution counts for a file in format 790 /// that's simple to iterate through for processing. 791 struct CoverageSegment { 792 /// The line where this segment begins. 793 unsigned Line; 794 /// The column where this segment begins. 795 unsigned Col; 796 /// The execution count, or zero if no count was recorded. 797 uint64_t Count; 798 /// When false, the segment was uninstrumented or skipped. 799 bool HasCount; 800 /// Whether this enters a new region or returns to a previous count. 801 bool IsRegionEntry; 802 /// Whether this enters a gap region. 803 bool IsGapRegion; 804 805 CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry) 806 : Line(Line), Col(Col), Count(0), HasCount(false), 807 IsRegionEntry(IsRegionEntry), IsGapRegion(false) {} 808 809 CoverageSegment(unsigned Line, unsigned Col, uint64_t Count, 810 bool IsRegionEntry, bool IsGapRegion = false, 811 bool IsBranchRegion = false) 812 : Line(Line), Col(Col), Count(Count), HasCount(true), 813 IsRegionEntry(IsRegionEntry), IsGapRegion(IsGapRegion) {} 814 815 friend bool operator==(const CoverageSegment &L, const CoverageSegment &R) { 816 return std::tie(L.Line, L.Col, L.Count, L.HasCount, L.IsRegionEntry, 817 L.IsGapRegion) == std::tie(R.Line, R.Col, R.Count, 818 R.HasCount, R.IsRegionEntry, 819 R.IsGapRegion); 820 } 821 }; 822 823 /// An instantiation group contains a \c FunctionRecord list, such that each 824 /// record corresponds to a distinct instantiation of the same function. 825 /// 826 /// Note that it's possible for a function to have more than one instantiation 827 /// (consider C++ template specializations or static inline functions). 828 class InstantiationGroup { 829 friend class CoverageMapping; 830 831 unsigned Line; 832 unsigned Col; 833 std::vector<const FunctionRecord *> Instantiations; 834 835 InstantiationGroup(unsigned Line, unsigned Col, 836 std::vector<const FunctionRecord *> Instantiations) 837 : Line(Line), Col(Col), Instantiations(std::move(Instantiations)) {} 838 839 public: 840 InstantiationGroup(const InstantiationGroup &) = delete; 841 InstantiationGroup(InstantiationGroup &&) = default; 842 843 /// Get the number of instantiations in this group. 844 size_t size() const { return Instantiations.size(); } 845 846 /// Get the line where the common function was defined. 847 unsigned getLine() const { return Line; } 848 849 /// Get the column where the common function was defined. 850 unsigned getColumn() const { return Col; } 851 852 /// Check if the instantiations in this group have a common mangled name. 853 bool hasName() const { 854 for (unsigned I = 1, E = Instantiations.size(); I < E; ++I) 855 if (Instantiations[I]->Name != Instantiations[0]->Name) 856 return false; 857 return true; 858 } 859 860 /// Get the common mangled name for instantiations in this group. 861 StringRef getName() const { 862 assert(hasName() && "Instantiations don't have a shared name"); 863 return Instantiations[0]->Name; 864 } 865 866 /// Get the total execution count of all instantiations in this group. 867 uint64_t getTotalExecutionCount() const { 868 uint64_t Count = 0; 869 for (const FunctionRecord *F : Instantiations) 870 Count += F->ExecutionCount; 871 return Count; 872 } 873 874 /// Get the instantiations in this group. 875 ArrayRef<const FunctionRecord *> getInstantiations() const { 876 return Instantiations; 877 } 878 }; 879 880 /// Coverage information to be processed or displayed. 881 /// 882 /// This represents the coverage of an entire file, expansion, or function. It 883 /// provides a sequence of CoverageSegments to iterate through, as well as the 884 /// list of expansions that can be further processed. 885 class CoverageData { 886 friend class CoverageMapping; 887 888 std::string Filename; 889 std::vector<CoverageSegment> Segments; 890 std::vector<ExpansionRecord> Expansions; 891 std::vector<CountedRegion> BranchRegions; 892 std::vector<MCDCRecord> MCDCRecords; 893 894 public: 895 CoverageData() = default; 896 897 CoverageData(StringRef Filename) : Filename(Filename) {} 898 899 /// Get the name of the file this data covers. 900 StringRef getFilename() const { return Filename; } 901 902 /// Get an iterator over the coverage segments for this object. The segments 903 /// are guaranteed to be uniqued and sorted by location. 904 std::vector<CoverageSegment>::const_iterator begin() const { 905 return Segments.begin(); 906 } 907 908 std::vector<CoverageSegment>::const_iterator end() const { 909 return Segments.end(); 910 } 911 912 bool empty() const { return Segments.empty(); } 913 914 /// Expansions that can be further processed. 915 ArrayRef<ExpansionRecord> getExpansions() const { return Expansions; } 916 917 /// Branches that can be further processed. 918 ArrayRef<CountedRegion> getBranches() const { return BranchRegions; } 919 920 /// MCDC Records that can be further processed. 921 ArrayRef<MCDCRecord> getMCDCRecords() const { return MCDCRecords; } 922 }; 923 924 /// The mapping of profile information to coverage data. 925 /// 926 /// This is the main interface to get coverage information, using a profile to 927 /// fill out execution counts. 928 class CoverageMapping { 929 DenseMap<size_t, DenseSet<size_t>> RecordProvenance; 930 std::vector<FunctionRecord> Functions; 931 DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices; 932 std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches; 933 934 CoverageMapping() = default; 935 936 // Load coverage records from readers. 937 static Error loadFromReaders( 938 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 939 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage); 940 941 // Load coverage records from file. 942 static Error 943 loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir, 944 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage, 945 bool &DataFound, 946 SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr); 947 948 /// Add a function record corresponding to \p Record. 949 Error loadFunctionRecord(const CoverageMappingRecord &Record, 950 IndexedInstrProfReader &ProfileReader); 951 952 /// Look up the indices for function records which are at least partially 953 /// defined in the specified file. This is guaranteed to return a superset of 954 /// such records: extra records not in the file may be included if there is 955 /// a hash collision on the filename. Clients must be robust to collisions. 956 ArrayRef<unsigned> 957 getImpreciseRecordIndicesForFilename(StringRef Filename) const; 958 959 public: 960 CoverageMapping(const CoverageMapping &) = delete; 961 CoverageMapping &operator=(const CoverageMapping &) = delete; 962 963 /// Load the coverage mapping using the given readers. 964 static Expected<std::unique_ptr<CoverageMapping>> 965 load(ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 966 IndexedInstrProfReader &ProfileReader); 967 968 /// Load the coverage mapping from the given object files and profile. If 969 /// \p Arches is non-empty, it must specify an architecture for each object. 970 /// Ignores non-instrumented object files unless all are not instrumented. 971 static Expected<std::unique_ptr<CoverageMapping>> 972 load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 973 vfs::FileSystem &FS, ArrayRef<StringRef> Arches = std::nullopt, 974 StringRef CompilationDir = "", 975 const object::BuildIDFetcher *BIDFetcher = nullptr, 976 bool CheckBinaryIDs = false); 977 978 /// The number of functions that couldn't have their profiles mapped. 979 /// 980 /// This is a count of functions whose profile is out of date or otherwise 981 /// can't be associated with any coverage information. 982 unsigned getMismatchedCount() const { return FuncHashMismatches.size(); } 983 984 /// A hash mismatch occurs when a profile record for a symbol does not have 985 /// the same hash as a coverage mapping record for the same symbol. This 986 /// returns a list of hash mismatches, where each mismatch is a pair of the 987 /// symbol name and its coverage mapping hash. 988 ArrayRef<std::pair<std::string, uint64_t>> getHashMismatches() const { 989 return FuncHashMismatches; 990 } 991 992 /// Returns a lexicographically sorted, unique list of files that are 993 /// covered. 994 std::vector<StringRef> getUniqueSourceFiles() const; 995 996 /// Get the coverage for a particular file. 997 /// 998 /// The given filename must be the name as recorded in the coverage 999 /// information. That is, only names returned from getUniqueSourceFiles will 1000 /// yield a result. 1001 CoverageData getCoverageForFile(StringRef Filename) const; 1002 1003 /// Get the coverage for a particular function. 1004 CoverageData getCoverageForFunction(const FunctionRecord &Function) const; 1005 1006 /// Get the coverage for an expansion within a coverage set. 1007 CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const; 1008 1009 /// Gets all of the functions covered by this profile. 1010 iterator_range<FunctionRecordIterator> getCoveredFunctions() const { 1011 return make_range(FunctionRecordIterator(Functions), 1012 FunctionRecordIterator()); 1013 } 1014 1015 /// Gets all of the functions in a particular file. 1016 iterator_range<FunctionRecordIterator> 1017 getCoveredFunctions(StringRef Filename) const { 1018 return make_range(FunctionRecordIterator(Functions, Filename), 1019 FunctionRecordIterator()); 1020 } 1021 1022 /// Get the list of function instantiation groups in a particular file. 1023 /// 1024 /// Every instantiation group in a program is attributed to exactly one file: 1025 /// the file in which the definition for the common function begins. 1026 std::vector<InstantiationGroup> 1027 getInstantiationGroups(StringRef Filename) const; 1028 }; 1029 1030 /// Coverage statistics for a single line. 1031 class LineCoverageStats { 1032 uint64_t ExecutionCount; 1033 bool HasMultipleRegions; 1034 bool Mapped; 1035 unsigned Line; 1036 ArrayRef<const CoverageSegment *> LineSegments; 1037 const CoverageSegment *WrappedSegment; 1038 1039 friend class LineCoverageIterator; 1040 LineCoverageStats() = default; 1041 1042 public: 1043 LineCoverageStats(ArrayRef<const CoverageSegment *> LineSegments, 1044 const CoverageSegment *WrappedSegment, unsigned Line); 1045 1046 uint64_t getExecutionCount() const { return ExecutionCount; } 1047 1048 bool hasMultipleRegions() const { return HasMultipleRegions; } 1049 1050 bool isMapped() const { return Mapped; } 1051 1052 unsigned getLine() const { return Line; } 1053 1054 ArrayRef<const CoverageSegment *> getLineSegments() const { 1055 return LineSegments; 1056 } 1057 1058 const CoverageSegment *getWrappedSegment() const { return WrappedSegment; } 1059 }; 1060 1061 /// An iterator over the \c LineCoverageStats objects for lines described by 1062 /// a \c CoverageData instance. 1063 class LineCoverageIterator 1064 : public iterator_facade_base<LineCoverageIterator, 1065 std::forward_iterator_tag, 1066 const LineCoverageStats> { 1067 public: 1068 LineCoverageIterator(const CoverageData &CD) 1069 : LineCoverageIterator(CD, CD.begin()->Line) {} 1070 1071 LineCoverageIterator(const CoverageData &CD, unsigned Line) 1072 : CD(CD), WrappedSegment(nullptr), Next(CD.begin()), Ended(false), 1073 Line(Line) { 1074 this->operator++(); 1075 } 1076 1077 bool operator==(const LineCoverageIterator &R) const { 1078 return &CD == &R.CD && Next == R.Next && Ended == R.Ended; 1079 } 1080 1081 const LineCoverageStats &operator*() const { return Stats; } 1082 1083 LineCoverageIterator &operator++(); 1084 1085 LineCoverageIterator getEnd() const { 1086 auto EndIt = *this; 1087 EndIt.Next = CD.end(); 1088 EndIt.Ended = true; 1089 return EndIt; 1090 } 1091 1092 private: 1093 const CoverageData &CD; 1094 const CoverageSegment *WrappedSegment; 1095 std::vector<CoverageSegment>::const_iterator Next; 1096 bool Ended; 1097 unsigned Line; 1098 SmallVector<const CoverageSegment *, 4> Segments; 1099 LineCoverageStats Stats; 1100 }; 1101 1102 /// Get a \c LineCoverageIterator range for the lines described by \p CD. 1103 static inline iterator_range<LineCoverageIterator> 1104 getLineCoverageStats(const coverage::CoverageData &CD) { 1105 auto Begin = LineCoverageIterator(CD); 1106 auto End = Begin.getEnd(); 1107 return make_range(Begin, End); 1108 } 1109 1110 // Coverage mappping data (V2) has the following layout: 1111 // IPSK_covmap: 1112 // [CoverageMapFileHeader] 1113 // [ArrayStart] 1114 // [CovMapFunctionRecordV2] 1115 // [CovMapFunctionRecordV2] 1116 // ... 1117 // [ArrayEnd] 1118 // [Encoded Filenames and Region Mapping Data] 1119 // 1120 // Coverage mappping data (V3) has the following layout: 1121 // IPSK_covmap: 1122 // [CoverageMapFileHeader] 1123 // [Encoded Filenames] 1124 // IPSK_covfun: 1125 // [ArrayStart] 1126 // odr_name_1: [CovMapFunctionRecordV3] 1127 // odr_name_2: [CovMapFunctionRecordV3] 1128 // ... 1129 // [ArrayEnd] 1130 // 1131 // Both versions of the coverage mapping format encode the same information, 1132 // but the V3 format does so more compactly by taking advantage of linkonce_odr 1133 // semantics (it allows exactly 1 function record per name reference). 1134 1135 /// This namespace defines accessors shared by different versions of coverage 1136 /// mapping records. 1137 namespace accessors { 1138 1139 /// Return the structural hash associated with the function. 1140 template <class FuncRecordTy, llvm::endianness Endian> 1141 uint64_t getFuncHash(const FuncRecordTy *Record) { 1142 return support::endian::byte_swap<uint64_t, Endian>(Record->FuncHash); 1143 } 1144 1145 /// Return the coverage map data size for the function. 1146 template <class FuncRecordTy, llvm::endianness Endian> 1147 uint64_t getDataSize(const FuncRecordTy *Record) { 1148 return support::endian::byte_swap<uint32_t, Endian>(Record->DataSize); 1149 } 1150 1151 /// Return the function lookup key. The value is considered opaque. 1152 template <class FuncRecordTy, llvm::endianness Endian> 1153 uint64_t getFuncNameRef(const FuncRecordTy *Record) { 1154 return support::endian::byte_swap<uint64_t, Endian>(Record->NameRef); 1155 } 1156 1157 /// Return the PGO name of the function. Used for formats in which the name is 1158 /// a hash. 1159 template <class FuncRecordTy, llvm::endianness Endian> 1160 Error getFuncNameViaRef(const FuncRecordTy *Record, 1161 InstrProfSymtab &ProfileNames, StringRef &FuncName) { 1162 uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record); 1163 FuncName = ProfileNames.getFuncOrVarName(NameRef); 1164 return Error::success(); 1165 } 1166 1167 /// Read coverage mapping out-of-line, from \p MappingBuf. This is used when the 1168 /// coverage mapping is attached to the file header, instead of to the function 1169 /// record. 1170 template <class FuncRecordTy, llvm::endianness Endian> 1171 StringRef getCoverageMappingOutOfLine(const FuncRecordTy *Record, 1172 const char *MappingBuf) { 1173 return {MappingBuf, size_t(getDataSize<FuncRecordTy, Endian>(Record))}; 1174 } 1175 1176 /// Advance to the next out-of-line coverage mapping and its associated 1177 /// function record. 1178 template <class FuncRecordTy, llvm::endianness Endian> 1179 std::pair<const char *, const FuncRecordTy *> 1180 advanceByOneOutOfLine(const FuncRecordTy *Record, const char *MappingBuf) { 1181 return {MappingBuf + getDataSize<FuncRecordTy, Endian>(Record), Record + 1}; 1182 } 1183 1184 } // end namespace accessors 1185 1186 LLVM_PACKED_START 1187 template <class IntPtrT> 1188 struct CovMapFunctionRecordV1 { 1189 using ThisT = CovMapFunctionRecordV1<IntPtrT>; 1190 1191 #define COVMAP_V1 1192 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 1193 #include "llvm/ProfileData/InstrProfData.inc" 1194 #undef COVMAP_V1 1195 CovMapFunctionRecordV1() = delete; 1196 1197 template <llvm::endianness Endian> uint64_t getFuncHash() const { 1198 return accessors::getFuncHash<ThisT, Endian>(this); 1199 } 1200 1201 template <llvm::endianness Endian> uint64_t getDataSize() const { 1202 return accessors::getDataSize<ThisT, Endian>(this); 1203 } 1204 1205 /// Return function lookup key. The value is consider opaque. 1206 template <llvm::endianness Endian> IntPtrT getFuncNameRef() const { 1207 return support::endian::byte_swap<IntPtrT, Endian>(NamePtr); 1208 } 1209 1210 /// Return the PGO name of the function. 1211 template <llvm::endianness Endian> 1212 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 1213 IntPtrT NameRef = getFuncNameRef<Endian>(); 1214 uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize); 1215 FuncName = ProfileNames.getFuncName(NameRef, NameS); 1216 if (NameS && FuncName.empty()) 1217 return make_error<CoverageMapError>(coveragemap_error::malformed, 1218 "function name is empty"); 1219 return Error::success(); 1220 } 1221 1222 template <llvm::endianness Endian> 1223 std::pair<const char *, const ThisT *> 1224 advanceByOne(const char *MappingBuf) const { 1225 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf); 1226 } 1227 1228 template <llvm::endianness Endian> uint64_t getFilenamesRef() const { 1229 llvm_unreachable("V1 function format does not contain a filenames ref"); 1230 } 1231 1232 template <llvm::endianness Endian> 1233 StringRef getCoverageMapping(const char *MappingBuf) const { 1234 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this, 1235 MappingBuf); 1236 } 1237 }; 1238 1239 struct CovMapFunctionRecordV2 { 1240 using ThisT = CovMapFunctionRecordV2; 1241 1242 #define COVMAP_V2 1243 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 1244 #include "llvm/ProfileData/InstrProfData.inc" 1245 #undef COVMAP_V2 1246 CovMapFunctionRecordV2() = delete; 1247 1248 template <llvm::endianness Endian> uint64_t getFuncHash() const { 1249 return accessors::getFuncHash<ThisT, Endian>(this); 1250 } 1251 1252 template <llvm::endianness Endian> uint64_t getDataSize() const { 1253 return accessors::getDataSize<ThisT, Endian>(this); 1254 } 1255 1256 template <llvm::endianness Endian> uint64_t getFuncNameRef() const { 1257 return accessors::getFuncNameRef<ThisT, Endian>(this); 1258 } 1259 1260 template <llvm::endianness Endian> 1261 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 1262 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames, 1263 FuncName); 1264 } 1265 1266 template <llvm::endianness Endian> 1267 std::pair<const char *, const ThisT *> 1268 advanceByOne(const char *MappingBuf) const { 1269 return accessors::advanceByOneOutOfLine<ThisT, Endian>(this, MappingBuf); 1270 } 1271 1272 template <llvm::endianness Endian> uint64_t getFilenamesRef() const { 1273 llvm_unreachable("V2 function format does not contain a filenames ref"); 1274 } 1275 1276 template <llvm::endianness Endian> 1277 StringRef getCoverageMapping(const char *MappingBuf) const { 1278 return accessors::getCoverageMappingOutOfLine<ThisT, Endian>(this, 1279 MappingBuf); 1280 } 1281 }; 1282 1283 struct CovMapFunctionRecordV3 { 1284 using ThisT = CovMapFunctionRecordV3; 1285 1286 #define COVMAP_V3 1287 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Type Name; 1288 #include "llvm/ProfileData/InstrProfData.inc" 1289 #undef COVMAP_V3 1290 CovMapFunctionRecordV3() = delete; 1291 1292 template <llvm::endianness Endian> uint64_t getFuncHash() const { 1293 return accessors::getFuncHash<ThisT, Endian>(this); 1294 } 1295 1296 template <llvm::endianness Endian> uint64_t getDataSize() const { 1297 return accessors::getDataSize<ThisT, Endian>(this); 1298 } 1299 1300 template <llvm::endianness Endian> uint64_t getFuncNameRef() const { 1301 return accessors::getFuncNameRef<ThisT, Endian>(this); 1302 } 1303 1304 template <llvm::endianness Endian> 1305 Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const { 1306 return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames, 1307 FuncName); 1308 } 1309 1310 /// Get the filename set reference. 1311 template <llvm::endianness Endian> uint64_t getFilenamesRef() const { 1312 return support::endian::byte_swap<uint64_t, Endian>(FilenamesRef); 1313 } 1314 1315 /// Read the inline coverage mapping. Ignore the buffer parameter, it is for 1316 /// out-of-line coverage mapping data only. 1317 template <llvm::endianness Endian> 1318 StringRef getCoverageMapping(const char *) const { 1319 return StringRef(&CoverageMapping, getDataSize<Endian>()); 1320 } 1321 1322 // Advance to the next inline coverage mapping and its associated function 1323 // record. Ignore the out-of-line coverage mapping buffer. 1324 template <llvm::endianness Endian> 1325 std::pair<const char *, const CovMapFunctionRecordV3 *> 1326 advanceByOne(const char *) const { 1327 assert(isAddrAligned(Align(8), this) && "Function record not aligned"); 1328 const char *Next = ((const char *)this) + sizeof(CovMapFunctionRecordV3) - 1329 sizeof(char) + getDataSize<Endian>(); 1330 // Each function record has an alignment of 8, so we need to adjust 1331 // alignment before reading the next record. 1332 Next += offsetToAlignedAddr(Next, Align(8)); 1333 return {nullptr, reinterpret_cast<const CovMapFunctionRecordV3 *>(Next)}; 1334 } 1335 }; 1336 1337 // Per module coverage mapping data header, i.e. CoverageMapFileHeader 1338 // documented above. 1339 struct CovMapHeader { 1340 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Type Name; 1341 #include "llvm/ProfileData/InstrProfData.inc" 1342 template <llvm::endianness Endian> uint32_t getNRecords() const { 1343 return support::endian::byte_swap<uint32_t, Endian>(NRecords); 1344 } 1345 1346 template <llvm::endianness Endian> uint32_t getFilenamesSize() const { 1347 return support::endian::byte_swap<uint32_t, Endian>(FilenamesSize); 1348 } 1349 1350 template <llvm::endianness Endian> uint32_t getCoverageSize() const { 1351 return support::endian::byte_swap<uint32_t, Endian>(CoverageSize); 1352 } 1353 1354 template <llvm::endianness Endian> uint32_t getVersion() const { 1355 return support::endian::byte_swap<uint32_t, Endian>(Version); 1356 } 1357 }; 1358 1359 LLVM_PACKED_END 1360 1361 enum CovMapVersion { 1362 Version1 = 0, 1363 // Function's name reference from CovMapFuncRecord is changed from raw 1364 // name string pointer to MD5 to support name section compression. Name 1365 // section is also compressed. 1366 Version2 = 1, 1367 // A new interpretation of the columnEnd field is added in order to mark 1368 // regions as gap areas. 1369 Version3 = 2, 1370 // Function records are named, uniqued, and moved to a dedicated section. 1371 Version4 = 3, 1372 // Branch regions referring to two counters are added 1373 Version5 = 4, 1374 // Compilation directory is stored separately and combined with relative 1375 // filenames to produce an absolute file path. 1376 Version6 = 5, 1377 // Branch regions extended and Decision Regions added for MC/DC. 1378 Version7 = 6, 1379 // The current version is Version7. 1380 CurrentVersion = INSTR_PROF_COVMAP_VERSION 1381 }; 1382 1383 // Correspond to "llvmcovm", in little-endian. 1384 constexpr uint64_t TestingFormatMagic = 0x6d766f636d766c6c; 1385 1386 enum class TestingFormatVersion : uint64_t { 1387 // The first version's number corresponds to the string "testdata" in 1388 // little-endian. This is for a historical reason. 1389 Version1 = 0x6174616474736574, 1390 // Version1 has a defect that it can't store multiple file records. Version2 1391 // fix this problem by adding a new field before the file records section. 1392 Version2 = 1, 1393 // The current testing format version is Version2. 1394 CurrentVersion = Version2 1395 }; 1396 1397 template <int CovMapVersion, class IntPtrT> struct CovMapTraits { 1398 using CovMapFuncRecordType = CovMapFunctionRecordV3; 1399 using NameRefType = uint64_t; 1400 }; 1401 1402 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version3, IntPtrT> { 1403 using CovMapFuncRecordType = CovMapFunctionRecordV2; 1404 using NameRefType = uint64_t; 1405 }; 1406 1407 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version2, IntPtrT> { 1408 using CovMapFuncRecordType = CovMapFunctionRecordV2; 1409 using NameRefType = uint64_t; 1410 }; 1411 1412 template <class IntPtrT> struct CovMapTraits<CovMapVersion::Version1, IntPtrT> { 1413 using CovMapFuncRecordType = CovMapFunctionRecordV1<IntPtrT>; 1414 using NameRefType = IntPtrT; 1415 }; 1416 1417 } // end namespace coverage 1418 1419 /// Provide DenseMapInfo for CounterExpression 1420 template<> struct DenseMapInfo<coverage::CounterExpression> { 1421 static inline coverage::CounterExpression getEmptyKey() { 1422 using namespace coverage; 1423 1424 return CounterExpression(CounterExpression::ExprKind::Subtract, 1425 Counter::getCounter(~0U), 1426 Counter::getCounter(~0U)); 1427 } 1428 1429 static inline coverage::CounterExpression getTombstoneKey() { 1430 using namespace coverage; 1431 1432 return CounterExpression(CounterExpression::ExprKind::Add, 1433 Counter::getCounter(~0U), 1434 Counter::getCounter(~0U)); 1435 } 1436 1437 static unsigned getHashValue(const coverage::CounterExpression &V) { 1438 return static_cast<unsigned>( 1439 hash_combine(V.Kind, V.LHS.getKind(), V.LHS.getCounterID(), 1440 V.RHS.getKind(), V.RHS.getCounterID())); 1441 } 1442 1443 static bool isEqual(const coverage::CounterExpression &LHS, 1444 const coverage::CounterExpression &RHS) { 1445 return LHS.Kind == RHS.Kind && LHS.LHS == RHS.LHS && LHS.RHS == RHS.RHS; 1446 } 1447 }; 1448 1449 } // end namespace llvm 1450 1451 #endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPING_H 1452