1 //===- CoverageMapping.cpp - Code coverage mapping support ----------------===// 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 // This file contains support for clang's and llvm's instrumentation based 10 // code coverage. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ProfileData/Coverage/CoverageMapping.h" 15 #include "llvm/ADT/ArrayRef.h" 16 #include "llvm/ADT/DenseMap.h" 17 #include "llvm/ADT/SmallBitVector.h" 18 #include "llvm/ADT/SmallVector.h" 19 #include "llvm/ADT/StringExtras.h" 20 #include "llvm/ADT/StringRef.h" 21 #include "llvm/Object/BuildID.h" 22 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 23 #include "llvm/ProfileData/InstrProfReader.h" 24 #include "llvm/Support/Debug.h" 25 #include "llvm/Support/Errc.h" 26 #include "llvm/Support/Error.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/MemoryBuffer.h" 29 #include "llvm/Support/VirtualFileSystem.h" 30 #include "llvm/Support/raw_ostream.h" 31 #include <algorithm> 32 #include <cassert> 33 #include <cmath> 34 #include <cstdint> 35 #include <iterator> 36 #include <map> 37 #include <memory> 38 #include <optional> 39 #include <string> 40 #include <system_error> 41 #include <utility> 42 #include <vector> 43 44 using namespace llvm; 45 using namespace coverage; 46 47 #define DEBUG_TYPE "coverage-mapping" 48 49 Counter CounterExpressionBuilder::get(const CounterExpression &E) { 50 auto It = ExpressionIndices.find(E); 51 if (It != ExpressionIndices.end()) 52 return Counter::getExpression(It->second); 53 unsigned I = Expressions.size(); 54 Expressions.push_back(E); 55 ExpressionIndices[E] = I; 56 return Counter::getExpression(I); 57 } 58 59 void CounterExpressionBuilder::extractTerms(Counter C, int Factor, 60 SmallVectorImpl<Term> &Terms) { 61 switch (C.getKind()) { 62 case Counter::Zero: 63 break; 64 case Counter::CounterValueReference: 65 Terms.emplace_back(C.getCounterID(), Factor); 66 break; 67 case Counter::Expression: 68 const auto &E = Expressions[C.getExpressionID()]; 69 extractTerms(E.LHS, Factor, Terms); 70 extractTerms( 71 E.RHS, E.Kind == CounterExpression::Subtract ? -Factor : Factor, Terms); 72 break; 73 } 74 } 75 76 Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) { 77 // Gather constant terms. 78 SmallVector<Term, 32> Terms; 79 extractTerms(ExpressionTree, +1, Terms); 80 81 // If there are no terms, this is just a zero. The algorithm below assumes at 82 // least one term. 83 if (Terms.size() == 0) 84 return Counter::getZero(); 85 86 // Group the terms by counter ID. 87 llvm::sort(Terms, [](const Term &LHS, const Term &RHS) { 88 return LHS.CounterID < RHS.CounterID; 89 }); 90 91 // Combine terms by counter ID to eliminate counters that sum to zero. 92 auto Prev = Terms.begin(); 93 for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) { 94 if (I->CounterID == Prev->CounterID) { 95 Prev->Factor += I->Factor; 96 continue; 97 } 98 ++Prev; 99 *Prev = *I; 100 } 101 Terms.erase(++Prev, Terms.end()); 102 103 Counter C; 104 // Create additions. We do this before subtractions to avoid constructs like 105 // ((0 - X) + Y), as opposed to (Y - X). 106 for (auto T : Terms) { 107 if (T.Factor <= 0) 108 continue; 109 for (int I = 0; I < T.Factor; ++I) 110 if (C.isZero()) 111 C = Counter::getCounter(T.CounterID); 112 else 113 C = get(CounterExpression(CounterExpression::Add, C, 114 Counter::getCounter(T.CounterID))); 115 } 116 117 // Create subtractions. 118 for (auto T : Terms) { 119 if (T.Factor >= 0) 120 continue; 121 for (int I = 0; I < -T.Factor; ++I) 122 C = get(CounterExpression(CounterExpression::Subtract, C, 123 Counter::getCounter(T.CounterID))); 124 } 125 return C; 126 } 127 128 Counter CounterExpressionBuilder::add(Counter LHS, Counter RHS, bool Simplify) { 129 auto Cnt = get(CounterExpression(CounterExpression::Add, LHS, RHS)); 130 return Simplify ? simplify(Cnt) : Cnt; 131 } 132 133 Counter CounterExpressionBuilder::subtract(Counter LHS, Counter RHS, 134 bool Simplify) { 135 auto Cnt = get(CounterExpression(CounterExpression::Subtract, LHS, RHS)); 136 return Simplify ? simplify(Cnt) : Cnt; 137 } 138 139 void CounterMappingContext::dump(const Counter &C, raw_ostream &OS) const { 140 switch (C.getKind()) { 141 case Counter::Zero: 142 OS << '0'; 143 return; 144 case Counter::CounterValueReference: 145 OS << '#' << C.getCounterID(); 146 break; 147 case Counter::Expression: { 148 if (C.getExpressionID() >= Expressions.size()) 149 return; 150 const auto &E = Expressions[C.getExpressionID()]; 151 OS << '('; 152 dump(E.LHS, OS); 153 OS << (E.Kind == CounterExpression::Subtract ? " - " : " + "); 154 dump(E.RHS, OS); 155 OS << ')'; 156 break; 157 } 158 } 159 if (CounterValues.empty()) 160 return; 161 Expected<int64_t> Value = evaluate(C); 162 if (auto E = Value.takeError()) { 163 consumeError(std::move(E)); 164 return; 165 } 166 OS << '[' << *Value << ']'; 167 } 168 169 Expected<int64_t> CounterMappingContext::evaluate(const Counter &C) const { 170 struct StackElem { 171 Counter ICounter; 172 int64_t LHS = 0; 173 enum { 174 KNeverVisited = 0, 175 KVisitedOnce = 1, 176 KVisitedTwice = 2, 177 } VisitCount = KNeverVisited; 178 }; 179 180 std::stack<StackElem> CounterStack; 181 CounterStack.push({C}); 182 183 int64_t LastPoppedValue; 184 185 while (!CounterStack.empty()) { 186 StackElem &Current = CounterStack.top(); 187 188 switch (Current.ICounter.getKind()) { 189 case Counter::Zero: 190 LastPoppedValue = 0; 191 CounterStack.pop(); 192 break; 193 case Counter::CounterValueReference: 194 if (Current.ICounter.getCounterID() >= CounterValues.size()) 195 return errorCodeToError(errc::argument_out_of_domain); 196 LastPoppedValue = CounterValues[Current.ICounter.getCounterID()]; 197 CounterStack.pop(); 198 break; 199 case Counter::Expression: { 200 if (Current.ICounter.getExpressionID() >= Expressions.size()) 201 return errorCodeToError(errc::argument_out_of_domain); 202 const auto &E = Expressions[Current.ICounter.getExpressionID()]; 203 if (Current.VisitCount == StackElem::KNeverVisited) { 204 CounterStack.push(StackElem{E.LHS}); 205 Current.VisitCount = StackElem::KVisitedOnce; 206 } else if (Current.VisitCount == StackElem::KVisitedOnce) { 207 Current.LHS = LastPoppedValue; 208 CounterStack.push(StackElem{E.RHS}); 209 Current.VisitCount = StackElem::KVisitedTwice; 210 } else { 211 int64_t LHS = Current.LHS; 212 int64_t RHS = LastPoppedValue; 213 LastPoppedValue = 214 E.Kind == CounterExpression::Subtract ? LHS - RHS : LHS + RHS; 215 CounterStack.pop(); 216 } 217 break; 218 } 219 } 220 } 221 222 return LastPoppedValue; 223 } 224 225 Expected<BitVector> CounterMappingContext::evaluateBitmap( 226 const CounterMappingRegion *MCDCDecision) const { 227 unsigned ID = MCDCDecision->MCDCParams.BitmapIdx; 228 unsigned NC = MCDCDecision->MCDCParams.NumConditions; 229 unsigned SizeInBits = llvm::alignTo(uint64_t(1) << NC, CHAR_BIT); 230 unsigned SizeInBytes = SizeInBits / CHAR_BIT; 231 232 ArrayRef<uint8_t> Bytes(&BitmapBytes[ID], SizeInBytes); 233 234 // Mask each bitmap byte into the BitVector. Go in reverse so that the 235 // bitvector can just be shifted over by one byte on each iteration. 236 BitVector Result(SizeInBits, false); 237 for (auto Byte = std::rbegin(Bytes); Byte != std::rend(Bytes); ++Byte) { 238 uint32_t Data = *Byte; 239 Result <<= CHAR_BIT; 240 Result.setBitsInMask(&Data, 1); 241 } 242 return Result; 243 } 244 245 class MCDCRecordProcessor { 246 /// A bitmap representing the executed test vectors for a boolean expression. 247 /// Each index of the bitmap corresponds to a possible test vector. An index 248 /// with a bit value of '1' indicates that the corresponding Test Vector 249 /// identified by that index was executed. 250 const BitVector &ExecutedTestVectorBitmap; 251 252 /// Decision Region to which the ExecutedTestVectorBitmap applies. 253 const CounterMappingRegion &Region; 254 255 /// Array of branch regions corresponding each conditions in the boolean 256 /// expression. 257 ArrayRef<const CounterMappingRegion *> Branches; 258 259 /// Total number of conditions in the boolean expression. 260 unsigned NumConditions; 261 262 /// Mapping of a condition ID to its corresponding branch region. 263 llvm::DenseMap<unsigned, const CounterMappingRegion *> Map; 264 265 /// Vector used to track whether a condition is constant folded. 266 MCDCRecord::BoolVector Folded; 267 268 /// Mapping of calculated MC/DC Independence Pairs for each condition. 269 MCDCRecord::TVPairMap IndependencePairs; 270 271 /// Total number of possible Test Vectors for the boolean expression. 272 MCDCRecord::TestVectors TestVectors; 273 274 /// Actual executed Test Vectors for the boolean expression, based on 275 /// ExecutedTestVectorBitmap. 276 MCDCRecord::TestVectors ExecVectors; 277 278 public: 279 MCDCRecordProcessor(const BitVector &Bitmap, 280 const CounterMappingRegion &Region, 281 ArrayRef<const CounterMappingRegion *> Branches) 282 : ExecutedTestVectorBitmap(Bitmap), Region(Region), Branches(Branches), 283 NumConditions(Region.MCDCParams.NumConditions), 284 Folded(NumConditions, false), IndependencePairs(NumConditions), 285 TestVectors((size_t)1 << NumConditions) {} 286 287 private: 288 void recordTestVector(MCDCRecord::TestVector &TV, 289 MCDCRecord::CondState Result) { 290 // Calculate an index that is used to identify the test vector in a vector 291 // of test vectors. This index also corresponds to the index values of an 292 // MCDC Region's bitmap (see findExecutedTestVectors()). 293 unsigned Index = 0; 294 for (auto Cond = std::rbegin(TV); Cond != std::rend(TV); ++Cond) { 295 Index <<= 1; 296 Index |= (*Cond == MCDCRecord::MCDC_True) ? 0x1 : 0x0; 297 } 298 299 // Copy the completed test vector to the vector of testvectors. 300 TestVectors[Index] = TV; 301 302 // The final value (T,F) is equal to the last non-dontcare state on the 303 // path (in a short-circuiting system). 304 TestVectors[Index].push_back(Result); 305 } 306 307 void shouldCopyOffTestVectorForTruePath(MCDCRecord::TestVector &TV, 308 unsigned ID) { 309 // Branch regions are hashed based on an ID. 310 const CounterMappingRegion *Branch = Map[ID]; 311 312 TV[ID - 1] = MCDCRecord::MCDC_True; 313 if (Branch->MCDCParams.TrueID > 0) 314 buildTestVector(TV, Branch->MCDCParams.TrueID); 315 else 316 recordTestVector(TV, MCDCRecord::MCDC_True); 317 } 318 319 void shouldCopyOffTestVectorForFalsePath(MCDCRecord::TestVector &TV, 320 unsigned ID) { 321 // Branch regions are hashed based on an ID. 322 const CounterMappingRegion *Branch = Map[ID]; 323 324 TV[ID - 1] = MCDCRecord::MCDC_False; 325 if (Branch->MCDCParams.FalseID > 0) 326 buildTestVector(TV, Branch->MCDCParams.FalseID); 327 else 328 recordTestVector(TV, MCDCRecord::MCDC_False); 329 } 330 331 /// Starting with the base test vector, build a comprehensive list of 332 /// possible test vectors by recursively walking the branch condition IDs 333 /// provided. Once an end node is reached, record the test vector in a vector 334 /// of test vectors that can be matched against during MC/DC analysis, and 335 /// then reset the positions to 'DontCare'. 336 void buildTestVector(MCDCRecord::TestVector &TV, unsigned ID = 1) { 337 shouldCopyOffTestVectorForTruePath(TV, ID); 338 shouldCopyOffTestVectorForFalsePath(TV, ID); 339 340 // Reset back to DontCare. 341 TV[ID - 1] = MCDCRecord::MCDC_DontCare; 342 } 343 344 /// Walk the bits in the bitmap. A bit set to '1' indicates that the test 345 /// vector at the corresponding index was executed during a test run. 346 void findExecutedTestVectors(const BitVector &ExecutedTestVectorBitmap) { 347 for (unsigned Idx = 0; Idx < ExecutedTestVectorBitmap.size(); ++Idx) { 348 if (ExecutedTestVectorBitmap[Idx] == 0) 349 continue; 350 assert(!TestVectors[Idx].empty() && "Test Vector doesn't exist."); 351 ExecVectors.push_back(TestVectors[Idx]); 352 } 353 } 354 355 /// For a given condition and two executed Test Vectors, A and B, see if the 356 /// two test vectors match forming an Independence Pair for the condition. 357 /// For two test vectors to match, the following must be satisfied: 358 /// - The condition's value in each test vector must be opposite. 359 /// - The result's value in each test vector must be opposite. 360 /// - All other conditions' values must be equal or marked as "don't care". 361 bool matchTestVectors(unsigned Aidx, unsigned Bidx, unsigned ConditionIdx) { 362 const MCDCRecord::TestVector &A = ExecVectors[Aidx]; 363 const MCDCRecord::TestVector &B = ExecVectors[Bidx]; 364 365 // If condition values in both A and B aren't opposites, no match. 366 // Because a value can be 0 (false), 1 (true), or -1 (DontCare), a check 367 // that "XOR != 1" will ensure that the values are opposites and that 368 // neither of them is a DontCare. 369 // 1 XOR 0 == 1 | 0 XOR 0 == 0 | -1 XOR 0 == -1 370 // 1 XOR 1 == 0 | 0 XOR 1 == 1 | -1 XOR 1 == -2 371 // 1 XOR -1 == -2 | 0 XOR -1 == -1 | -1 XOR -1 == 0 372 if ((A[ConditionIdx] ^ B[ConditionIdx]) != 1) 373 return false; 374 375 // If the results of both A and B aren't opposites, no match. 376 if ((A[NumConditions] ^ B[NumConditions]) != 1) 377 return false; 378 379 for (unsigned Idx = 0; Idx < NumConditions; ++Idx) { 380 // Look for other conditions that don't match. Skip over the given 381 // Condition as well as any conditions marked as "don't care". 382 const auto ARecordTyForCond = A[Idx]; 383 const auto BRecordTyForCond = B[Idx]; 384 if (Idx == ConditionIdx || 385 ARecordTyForCond == MCDCRecord::MCDC_DontCare || 386 BRecordTyForCond == MCDCRecord::MCDC_DontCare) 387 continue; 388 389 // If there is a condition mismatch with any of the other conditions, 390 // there is no match for the test vectors. 391 if (ARecordTyForCond != BRecordTyForCond) 392 return false; 393 } 394 395 // Otherwise, match. 396 return true; 397 } 398 399 /// Find all possible Independence Pairs for a boolean expression given its 400 /// executed Test Vectors. This process involves looking at each condition 401 /// and attempting to find two Test Vectors that "match", giving us a pair. 402 void findIndependencePairs() { 403 unsigned NumTVs = ExecVectors.size(); 404 405 // For each condition. 406 for (unsigned C = 0; C < NumConditions; ++C) { 407 bool PairFound = false; 408 409 // For each executed test vector. 410 for (unsigned I = 0; !PairFound && I < NumTVs; ++I) { 411 // Compared to every other executed test vector. 412 for (unsigned J = 0; !PairFound && J < NumTVs; ++J) { 413 if (I == J) 414 continue; 415 416 // If a matching pair of vectors is found, record them. 417 if ((PairFound = matchTestVectors(I, J, C))) 418 IndependencePairs[C] = std::make_pair(I + 1, J + 1); 419 } 420 } 421 } 422 } 423 424 public: 425 /// Process the MC/DC Record in order to produce a result for a boolean 426 /// expression. This process includes tracking the conditions that comprise 427 /// the decision region, calculating the list of all possible test vectors, 428 /// marking the executed test vectors, and then finding an Independence Pair 429 /// out of the executed test vectors for each condition in the boolean 430 /// expression. A condition is tracked to ensure that its ID can be mapped to 431 /// its ordinal position in the boolean expression. The condition's source 432 /// location is also tracked, as well as whether it is constant folded (in 433 /// which case it is excuded from the metric). 434 MCDCRecord processMCDCRecord() { 435 unsigned I = 0; 436 MCDCRecord::CondIDMap PosToID; 437 MCDCRecord::LineColPairMap CondLoc; 438 439 // Walk the Record's BranchRegions (representing Conditions) in order to: 440 // - Hash the condition based on its corresponding ID. This will be used to 441 // calculate the test vectors. 442 // - Keep a map of the condition's ordinal position (1, 2, 3, 4) to its 443 // actual ID. This will be used to visualize the conditions in the 444 // correct order. 445 // - Keep track of the condition source location. This will be used to 446 // visualize where the condition is. 447 // - Record whether the condition is constant folded so that we exclude it 448 // from being measured. 449 for (const auto *B : Branches) { 450 Map[B->MCDCParams.ID] = B; 451 PosToID[I] = B->MCDCParams.ID - 1; 452 CondLoc[I] = B->startLoc(); 453 Folded[I++] = (B->Count.isZero() && B->FalseCount.isZero()); 454 } 455 456 // Initialize a base test vector as 'DontCare'. 457 MCDCRecord::TestVector TV(NumConditions, MCDCRecord::MCDC_DontCare); 458 459 // Use the base test vector to build the list of all possible test vectors. 460 buildTestVector(TV); 461 462 // Using Profile Bitmap from runtime, mark the executed test vectors. 463 findExecutedTestVectors(ExecutedTestVectorBitmap); 464 465 // Compare executed test vectors against each other to find an independence 466 // pairs for each condition. This processing takes the most time. 467 findIndependencePairs(); 468 469 // Record Test vectors, executed vectors, and independence pairs. 470 MCDCRecord Res(Region, ExecVectors, IndependencePairs, Folded, PosToID, 471 CondLoc); 472 return Res; 473 } 474 }; 475 476 Expected<MCDCRecord> CounterMappingContext::evaluateMCDCRegion( 477 const CounterMappingRegion &Region, 478 const BitVector &ExecutedTestVectorBitmap, 479 ArrayRef<const CounterMappingRegion *> Branches) { 480 481 MCDCRecordProcessor MCDCProcessor(ExecutedTestVectorBitmap, Region, Branches); 482 return MCDCProcessor.processMCDCRecord(); 483 } 484 485 unsigned CounterMappingContext::getMaxCounterID(const Counter &C) const { 486 struct StackElem { 487 Counter ICounter; 488 int64_t LHS = 0; 489 enum { 490 KNeverVisited = 0, 491 KVisitedOnce = 1, 492 KVisitedTwice = 2, 493 } VisitCount = KNeverVisited; 494 }; 495 496 std::stack<StackElem> CounterStack; 497 CounterStack.push({C}); 498 499 int64_t LastPoppedValue; 500 501 while (!CounterStack.empty()) { 502 StackElem &Current = CounterStack.top(); 503 504 switch (Current.ICounter.getKind()) { 505 case Counter::Zero: 506 LastPoppedValue = 0; 507 CounterStack.pop(); 508 break; 509 case Counter::CounterValueReference: 510 LastPoppedValue = Current.ICounter.getCounterID(); 511 CounterStack.pop(); 512 break; 513 case Counter::Expression: { 514 if (Current.ICounter.getExpressionID() >= Expressions.size()) { 515 LastPoppedValue = 0; 516 CounterStack.pop(); 517 } else { 518 const auto &E = Expressions[Current.ICounter.getExpressionID()]; 519 if (Current.VisitCount == StackElem::KNeverVisited) { 520 CounterStack.push(StackElem{E.LHS}); 521 Current.VisitCount = StackElem::KVisitedOnce; 522 } else if (Current.VisitCount == StackElem::KVisitedOnce) { 523 Current.LHS = LastPoppedValue; 524 CounterStack.push(StackElem{E.RHS}); 525 Current.VisitCount = StackElem::KVisitedTwice; 526 } else { 527 int64_t LHS = Current.LHS; 528 int64_t RHS = LastPoppedValue; 529 LastPoppedValue = std::max(LHS, RHS); 530 CounterStack.pop(); 531 } 532 } 533 break; 534 } 535 } 536 } 537 538 return LastPoppedValue; 539 } 540 541 void FunctionRecordIterator::skipOtherFiles() { 542 while (Current != Records.end() && !Filename.empty() && 543 Filename != Current->Filenames[0]) 544 ++Current; 545 if (Current == Records.end()) 546 *this = FunctionRecordIterator(); 547 } 548 549 ArrayRef<unsigned> CoverageMapping::getImpreciseRecordIndicesForFilename( 550 StringRef Filename) const { 551 size_t FilenameHash = hash_value(Filename); 552 auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash); 553 if (RecordIt == FilenameHash2RecordIndices.end()) 554 return {}; 555 return RecordIt->second; 556 } 557 558 static unsigned getMaxCounterID(const CounterMappingContext &Ctx, 559 const CoverageMappingRecord &Record) { 560 unsigned MaxCounterID = 0; 561 for (const auto &Region : Record.MappingRegions) { 562 MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count)); 563 } 564 return MaxCounterID; 565 } 566 567 static unsigned getMaxBitmapSize(const CounterMappingContext &Ctx, 568 const CoverageMappingRecord &Record) { 569 unsigned MaxBitmapID = 0; 570 unsigned NumConditions = 0; 571 // The last DecisionRegion has the highest bitmap byte index used in the 572 // function, which when combined with its number of conditions, yields the 573 // full bitmap size. 574 for (const auto &Region : reverse(Record.MappingRegions)) { 575 if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) { 576 MaxBitmapID = Region.MCDCParams.BitmapIdx; 577 NumConditions = Region.MCDCParams.NumConditions; 578 break; 579 } 580 } 581 unsigned SizeInBits = llvm::alignTo(uint64_t(1) << NumConditions, CHAR_BIT); 582 return MaxBitmapID + (SizeInBits / CHAR_BIT); 583 } 584 585 Error CoverageMapping::loadFunctionRecord( 586 const CoverageMappingRecord &Record, 587 IndexedInstrProfReader &ProfileReader) { 588 StringRef OrigFuncName = Record.FunctionName; 589 if (OrigFuncName.empty()) 590 return make_error<CoverageMapError>(coveragemap_error::malformed, 591 "record function name is empty"); 592 593 if (Record.Filenames.empty()) 594 OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName); 595 else 596 OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]); 597 598 CounterMappingContext Ctx(Record.Expressions); 599 600 std::vector<uint64_t> Counts; 601 if (Error E = ProfileReader.getFunctionCounts(Record.FunctionName, 602 Record.FunctionHash, Counts)) { 603 instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E))); 604 if (IPE == instrprof_error::hash_mismatch) { 605 FuncHashMismatches.emplace_back(std::string(Record.FunctionName), 606 Record.FunctionHash); 607 return Error::success(); 608 } 609 if (IPE != instrprof_error::unknown_function) 610 return make_error<InstrProfError>(IPE); 611 Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0); 612 } 613 Ctx.setCounts(Counts); 614 615 std::vector<uint8_t> BitmapBytes; 616 if (Error E = ProfileReader.getFunctionBitmapBytes( 617 Record.FunctionName, Record.FunctionHash, BitmapBytes)) { 618 instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E))); 619 if (IPE == instrprof_error::hash_mismatch) { 620 FuncHashMismatches.emplace_back(std::string(Record.FunctionName), 621 Record.FunctionHash); 622 return Error::success(); 623 } 624 if (IPE != instrprof_error::unknown_function) 625 return make_error<InstrProfError>(IPE); 626 BitmapBytes.assign(getMaxBitmapSize(Ctx, Record) + 1, 0); 627 } 628 Ctx.setBitmapBytes(BitmapBytes); 629 630 assert(!Record.MappingRegions.empty() && "Function has no regions"); 631 632 // This coverage record is a zero region for a function that's unused in 633 // some TU, but used in a different TU. Ignore it. The coverage maps from the 634 // the other TU will either be loaded (providing full region counts) or they 635 // won't (in which case we don't unintuitively report functions as uncovered 636 // when they have non-zero counts in the profile). 637 if (Record.MappingRegions.size() == 1 && 638 Record.MappingRegions[0].Count.isZero() && Counts[0] > 0) 639 return Error::success(); 640 641 unsigned NumConds = 0; 642 const CounterMappingRegion *MCDCDecision; 643 std::vector<const CounterMappingRegion *> MCDCBranches; 644 645 FunctionRecord Function(OrigFuncName, Record.Filenames); 646 for (const auto &Region : Record.MappingRegions) { 647 // If an MCDCDecisionRegion is seen, track the BranchRegions that follow 648 // it according to Region.NumConditions. 649 if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) { 650 assert(NumConds == 0); 651 MCDCDecision = &Region; 652 NumConds = Region.MCDCParams.NumConditions; 653 continue; 654 } 655 Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count); 656 if (auto E = ExecutionCount.takeError()) { 657 consumeError(std::move(E)); 658 return Error::success(); 659 } 660 Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount); 661 if (auto E = AltExecutionCount.takeError()) { 662 consumeError(std::move(E)); 663 return Error::success(); 664 } 665 Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount); 666 667 // If a MCDCDecisionRegion was seen, store the BranchRegions that 668 // correspond to it in a vector, according to the number of conditions 669 // recorded for the region (tracked by NumConds). 670 if (NumConds > 0 && Region.Kind == CounterMappingRegion::MCDCBranchRegion) { 671 MCDCBranches.push_back(&Region); 672 673 // As we move through all of the MCDCBranchRegions that follow the 674 // MCDCDecisionRegion, decrement NumConds to make sure we account for 675 // them all before we calculate the bitmap of executed test vectors. 676 if (--NumConds == 0) { 677 // Evaluating the test vector bitmap for the decision region entails 678 // calculating precisely what bits are pertinent to this region alone. 679 // This is calculated based on the recorded offset into the global 680 // profile bitmap; the length is calculated based on the recorded 681 // number of conditions. 682 Expected<BitVector> ExecutedTestVectorBitmap = 683 Ctx.evaluateBitmap(MCDCDecision); 684 if (auto E = ExecutedTestVectorBitmap.takeError()) { 685 consumeError(std::move(E)); 686 return Error::success(); 687 } 688 689 // Since the bitmap identifies the executed test vectors for an MC/DC 690 // DecisionRegion, all of the information is now available to process. 691 // This is where the bulk of the MC/DC progressing takes place. 692 Expected<MCDCRecord> Record = Ctx.evaluateMCDCRegion( 693 *MCDCDecision, *ExecutedTestVectorBitmap, MCDCBranches); 694 if (auto E = Record.takeError()) { 695 consumeError(std::move(E)); 696 return Error::success(); 697 } 698 699 // Save the MC/DC Record so that it can be visualized later. 700 Function.pushMCDCRecord(*Record); 701 MCDCBranches.clear(); 702 } 703 } 704 } 705 706 // Don't create records for (filenames, function) pairs we've already seen. 707 auto FilenamesHash = hash_combine_range(Record.Filenames.begin(), 708 Record.Filenames.end()); 709 if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second) 710 return Error::success(); 711 712 Functions.push_back(std::move(Function)); 713 714 // Performance optimization: keep track of the indices of the function records 715 // which correspond to each filename. This can be used to substantially speed 716 // up queries for coverage info in a file. 717 unsigned RecordIndex = Functions.size() - 1; 718 for (StringRef Filename : Record.Filenames) { 719 auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)]; 720 // Note that there may be duplicates in the filename set for a function 721 // record, because of e.g. macro expansions in the function in which both 722 // the macro and the function are defined in the same file. 723 if (RecordIndices.empty() || RecordIndices.back() != RecordIndex) 724 RecordIndices.push_back(RecordIndex); 725 } 726 727 return Error::success(); 728 } 729 730 // This function is for memory optimization by shortening the lifetimes 731 // of CoverageMappingReader instances. 732 Error CoverageMapping::loadFromReaders( 733 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 734 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage) { 735 for (const auto &CoverageReader : CoverageReaders) { 736 for (auto RecordOrErr : *CoverageReader) { 737 if (Error E = RecordOrErr.takeError()) 738 return E; 739 const auto &Record = *RecordOrErr; 740 if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader)) 741 return E; 742 } 743 } 744 return Error::success(); 745 } 746 747 Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load( 748 ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders, 749 IndexedInstrProfReader &ProfileReader) { 750 auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); 751 if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage)) 752 return std::move(E); 753 return std::move(Coverage); 754 } 755 756 // If E is a no_data_found error, returns success. Otherwise returns E. 757 static Error handleMaybeNoDataFoundError(Error E) { 758 return handleErrors( 759 std::move(E), [](const CoverageMapError &CME) { 760 if (CME.get() == coveragemap_error::no_data_found) 761 return static_cast<Error>(Error::success()); 762 return make_error<CoverageMapError>(CME.get(), CME.getMessage()); 763 }); 764 } 765 766 Error CoverageMapping::loadFromFile( 767 StringRef Filename, StringRef Arch, StringRef CompilationDir, 768 IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage, 769 bool &DataFound, SmallVectorImpl<object::BuildID> *FoundBinaryIDs) { 770 auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN( 771 Filename, /*IsText=*/false, /*RequiresNullTerminator=*/false); 772 if (std::error_code EC = CovMappingBufOrErr.getError()) 773 return createFileError(Filename, errorCodeToError(EC)); 774 MemoryBufferRef CovMappingBufRef = 775 CovMappingBufOrErr.get()->getMemBufferRef(); 776 SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers; 777 778 SmallVector<object::BuildIDRef> BinaryIDs; 779 auto CoverageReadersOrErr = BinaryCoverageReader::create( 780 CovMappingBufRef, Arch, Buffers, CompilationDir, 781 FoundBinaryIDs ? &BinaryIDs : nullptr); 782 if (Error E = CoverageReadersOrErr.takeError()) { 783 E = handleMaybeNoDataFoundError(std::move(E)); 784 if (E) 785 return createFileError(Filename, std::move(E)); 786 return E; 787 } 788 789 SmallVector<std::unique_ptr<CoverageMappingReader>, 4> Readers; 790 for (auto &Reader : CoverageReadersOrErr.get()) 791 Readers.push_back(std::move(Reader)); 792 if (FoundBinaryIDs && !Readers.empty()) { 793 llvm::append_range(*FoundBinaryIDs, 794 llvm::map_range(BinaryIDs, [](object::BuildIDRef BID) { 795 return object::BuildID(BID); 796 })); 797 } 798 DataFound |= !Readers.empty(); 799 if (Error E = loadFromReaders(Readers, ProfileReader, Coverage)) 800 return createFileError(Filename, std::move(E)); 801 return Error::success(); 802 } 803 804 Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load( 805 ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename, 806 vfs::FileSystem &FS, ArrayRef<StringRef> Arches, StringRef CompilationDir, 807 const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs) { 808 auto ProfileReaderOrErr = IndexedInstrProfReader::create(ProfileFilename, FS); 809 if (Error E = ProfileReaderOrErr.takeError()) 810 return createFileError(ProfileFilename, std::move(E)); 811 auto ProfileReader = std::move(ProfileReaderOrErr.get()); 812 auto Coverage = std::unique_ptr<CoverageMapping>(new CoverageMapping()); 813 bool DataFound = false; 814 815 auto GetArch = [&](size_t Idx) { 816 if (Arches.empty()) 817 return StringRef(); 818 if (Arches.size() == 1) 819 return Arches.front(); 820 return Arches[Idx]; 821 }; 822 823 SmallVector<object::BuildID> FoundBinaryIDs; 824 for (const auto &File : llvm::enumerate(ObjectFilenames)) { 825 if (Error E = 826 loadFromFile(File.value(), GetArch(File.index()), CompilationDir, 827 *ProfileReader, *Coverage, DataFound, &FoundBinaryIDs)) 828 return std::move(E); 829 } 830 831 if (BIDFetcher) { 832 std::vector<object::BuildID> ProfileBinaryIDs; 833 if (Error E = ProfileReader->readBinaryIds(ProfileBinaryIDs)) 834 return createFileError(ProfileFilename, std::move(E)); 835 836 SmallVector<object::BuildIDRef> BinaryIDsToFetch; 837 if (!ProfileBinaryIDs.empty()) { 838 const auto &Compare = [](object::BuildIDRef A, object::BuildIDRef B) { 839 return std::lexicographical_compare(A.begin(), A.end(), B.begin(), 840 B.end()); 841 }; 842 llvm::sort(FoundBinaryIDs, Compare); 843 std::set_difference( 844 ProfileBinaryIDs.begin(), ProfileBinaryIDs.end(), 845 FoundBinaryIDs.begin(), FoundBinaryIDs.end(), 846 std::inserter(BinaryIDsToFetch, BinaryIDsToFetch.end()), Compare); 847 } 848 849 for (object::BuildIDRef BinaryID : BinaryIDsToFetch) { 850 std::optional<std::string> PathOpt = BIDFetcher->fetch(BinaryID); 851 if (PathOpt) { 852 std::string Path = std::move(*PathOpt); 853 StringRef Arch = Arches.size() == 1 ? Arches.front() : StringRef(); 854 if (Error E = loadFromFile(Path, Arch, CompilationDir, *ProfileReader, 855 *Coverage, DataFound)) 856 return std::move(E); 857 } else if (CheckBinaryIDs) { 858 return createFileError( 859 ProfileFilename, 860 createStringError(errc::no_such_file_or_directory, 861 "Missing binary ID: " + 862 llvm::toHex(BinaryID, /*LowerCase=*/true))); 863 } 864 } 865 } 866 867 if (!DataFound) 868 return createFileError( 869 join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "), 870 make_error<CoverageMapError>(coveragemap_error::no_data_found)); 871 return std::move(Coverage); 872 } 873 874 namespace { 875 876 /// Distributes functions into instantiation sets. 877 /// 878 /// An instantiation set is a collection of functions that have the same source 879 /// code, ie, template functions specializations. 880 class FunctionInstantiationSetCollector { 881 using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>; 882 MapT InstantiatedFunctions; 883 884 public: 885 void insert(const FunctionRecord &Function, unsigned FileID) { 886 auto I = Function.CountedRegions.begin(), E = Function.CountedRegions.end(); 887 while (I != E && I->FileID != FileID) 888 ++I; 889 assert(I != E && "function does not cover the given file"); 890 auto &Functions = InstantiatedFunctions[I->startLoc()]; 891 Functions.push_back(&Function); 892 } 893 894 MapT::iterator begin() { return InstantiatedFunctions.begin(); } 895 MapT::iterator end() { return InstantiatedFunctions.end(); } 896 }; 897 898 class SegmentBuilder { 899 std::vector<CoverageSegment> &Segments; 900 SmallVector<const CountedRegion *, 8> ActiveRegions; 901 902 SegmentBuilder(std::vector<CoverageSegment> &Segments) : Segments(Segments) {} 903 904 /// Emit a segment with the count from \p Region starting at \p StartLoc. 905 // 906 /// \p IsRegionEntry: The segment is at the start of a new non-gap region. 907 /// \p EmitSkippedRegion: The segment must be emitted as a skipped region. 908 void startSegment(const CountedRegion &Region, LineColPair StartLoc, 909 bool IsRegionEntry, bool EmitSkippedRegion = false) { 910 bool HasCount = !EmitSkippedRegion && 911 (Region.Kind != CounterMappingRegion::SkippedRegion); 912 913 // If the new segment wouldn't affect coverage rendering, skip it. 914 if (!Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) { 915 const auto &Last = Segments.back(); 916 if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount && 917 !Last.IsRegionEntry) 918 return; 919 } 920 921 if (HasCount) 922 Segments.emplace_back(StartLoc.first, StartLoc.second, 923 Region.ExecutionCount, IsRegionEntry, 924 Region.Kind == CounterMappingRegion::GapRegion); 925 else 926 Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry); 927 928 LLVM_DEBUG({ 929 const auto &Last = Segments.back(); 930 dbgs() << "Segment at " << Last.Line << ":" << Last.Col 931 << " (count = " << Last.Count << ")" 932 << (Last.IsRegionEntry ? ", RegionEntry" : "") 933 << (!Last.HasCount ? ", Skipped" : "") 934 << (Last.IsGapRegion ? ", Gap" : "") << "\n"; 935 }); 936 } 937 938 /// Emit segments for active regions which end before \p Loc. 939 /// 940 /// \p Loc: The start location of the next region. If std::nullopt, all active 941 /// regions are completed. 942 /// \p FirstCompletedRegion: Index of the first completed region. 943 void completeRegionsUntil(std::optional<LineColPair> Loc, 944 unsigned FirstCompletedRegion) { 945 // Sort the completed regions by end location. This makes it simple to 946 // emit closing segments in sorted order. 947 auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion; 948 std::stable_sort(CompletedRegionsIt, ActiveRegions.end(), 949 [](const CountedRegion *L, const CountedRegion *R) { 950 return L->endLoc() < R->endLoc(); 951 }); 952 953 // Emit segments for all completed regions. 954 for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E; 955 ++I) { 956 const auto *CompletedRegion = ActiveRegions[I]; 957 assert((!Loc || CompletedRegion->endLoc() <= *Loc) && 958 "Completed region ends after start of new region"); 959 960 const auto *PrevCompletedRegion = ActiveRegions[I - 1]; 961 auto CompletedSegmentLoc = PrevCompletedRegion->endLoc(); 962 963 // Don't emit any more segments if they start where the new region begins. 964 if (Loc && CompletedSegmentLoc == *Loc) 965 break; 966 967 // Don't emit a segment if the next completed region ends at the same 968 // location as this one. 969 if (CompletedSegmentLoc == CompletedRegion->endLoc()) 970 continue; 971 972 // Use the count from the last completed region which ends at this loc. 973 for (unsigned J = I + 1; J < E; ++J) 974 if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc()) 975 CompletedRegion = ActiveRegions[J]; 976 977 startSegment(*CompletedRegion, CompletedSegmentLoc, false); 978 } 979 980 auto Last = ActiveRegions.back(); 981 if (FirstCompletedRegion && Last->endLoc() != *Loc) { 982 // If there's a gap after the end of the last completed region and the 983 // start of the new region, use the last active region to fill the gap. 984 startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(), 985 false); 986 } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) { 987 // Emit a skipped segment if there are no more active regions. This 988 // ensures that gaps between functions are marked correctly. 989 startSegment(*Last, Last->endLoc(), false, true); 990 } 991 992 // Pop the completed regions. 993 ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end()); 994 } 995 996 void buildSegmentsImpl(ArrayRef<CountedRegion> Regions) { 997 for (const auto &CR : enumerate(Regions)) { 998 auto CurStartLoc = CR.value().startLoc(); 999 1000 // Active regions which end before the current region need to be popped. 1001 auto CompletedRegions = 1002 std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(), 1003 [&](const CountedRegion *Region) { 1004 return !(Region->endLoc() <= CurStartLoc); 1005 }); 1006 if (CompletedRegions != ActiveRegions.end()) { 1007 unsigned FirstCompletedRegion = 1008 std::distance(ActiveRegions.begin(), CompletedRegions); 1009 completeRegionsUntil(CurStartLoc, FirstCompletedRegion); 1010 } 1011 1012 bool GapRegion = CR.value().Kind == CounterMappingRegion::GapRegion; 1013 1014 // Try to emit a segment for the current region. 1015 if (CurStartLoc == CR.value().endLoc()) { 1016 // Avoid making zero-length regions active. If it's the last region, 1017 // emit a skipped segment. Otherwise use its predecessor's count. 1018 const bool Skipped = 1019 (CR.index() + 1) == Regions.size() || 1020 CR.value().Kind == CounterMappingRegion::SkippedRegion; 1021 startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(), 1022 CurStartLoc, !GapRegion, Skipped); 1023 // If it is skipped segment, create a segment with last pushed 1024 // regions's count at CurStartLoc. 1025 if (Skipped && !ActiveRegions.empty()) 1026 startSegment(*ActiveRegions.back(), CurStartLoc, false); 1027 continue; 1028 } 1029 if (CR.index() + 1 == Regions.size() || 1030 CurStartLoc != Regions[CR.index() + 1].startLoc()) { 1031 // Emit a segment if the next region doesn't start at the same location 1032 // as this one. 1033 startSegment(CR.value(), CurStartLoc, !GapRegion); 1034 } 1035 1036 // This region is active (i.e not completed). 1037 ActiveRegions.push_back(&CR.value()); 1038 } 1039 1040 // Complete any remaining active regions. 1041 if (!ActiveRegions.empty()) 1042 completeRegionsUntil(std::nullopt, 0); 1043 } 1044 1045 /// Sort a nested sequence of regions from a single file. 1046 static void sortNestedRegions(MutableArrayRef<CountedRegion> Regions) { 1047 llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) { 1048 if (LHS.startLoc() != RHS.startLoc()) 1049 return LHS.startLoc() < RHS.startLoc(); 1050 if (LHS.endLoc() != RHS.endLoc()) 1051 // When LHS completely contains RHS, we sort LHS first. 1052 return RHS.endLoc() < LHS.endLoc(); 1053 // If LHS and RHS cover the same area, we need to sort them according 1054 // to their kinds so that the most suitable region will become "active" 1055 // in combineRegions(). Because we accumulate counter values only from 1056 // regions of the same kind as the first region of the area, prefer 1057 // CodeRegion to ExpansionRegion and ExpansionRegion to SkippedRegion. 1058 static_assert(CounterMappingRegion::CodeRegion < 1059 CounterMappingRegion::ExpansionRegion && 1060 CounterMappingRegion::ExpansionRegion < 1061 CounterMappingRegion::SkippedRegion, 1062 "Unexpected order of region kind values"); 1063 return LHS.Kind < RHS.Kind; 1064 }); 1065 } 1066 1067 /// Combine counts of regions which cover the same area. 1068 static ArrayRef<CountedRegion> 1069 combineRegions(MutableArrayRef<CountedRegion> Regions) { 1070 if (Regions.empty()) 1071 return Regions; 1072 auto Active = Regions.begin(); 1073 auto End = Regions.end(); 1074 for (auto I = Regions.begin() + 1; I != End; ++I) { 1075 if (Active->startLoc() != I->startLoc() || 1076 Active->endLoc() != I->endLoc()) { 1077 // Shift to the next region. 1078 ++Active; 1079 if (Active != I) 1080 *Active = *I; 1081 continue; 1082 } 1083 // Merge duplicate region. 1084 // If CodeRegions and ExpansionRegions cover the same area, it's probably 1085 // a macro which is fully expanded to another macro. In that case, we need 1086 // to accumulate counts only from CodeRegions, or else the area will be 1087 // counted twice. 1088 // On the other hand, a macro may have a nested macro in its body. If the 1089 // outer macro is used several times, the ExpansionRegion for the nested 1090 // macro will also be added several times. These ExpansionRegions cover 1091 // the same source locations and have to be combined to reach the correct 1092 // value for that area. 1093 // We add counts of the regions of the same kind as the active region 1094 // to handle the both situations. 1095 if (I->Kind == Active->Kind) 1096 Active->ExecutionCount += I->ExecutionCount; 1097 } 1098 return Regions.drop_back(std::distance(++Active, End)); 1099 } 1100 1101 public: 1102 /// Build a sorted list of CoverageSegments from a list of Regions. 1103 static std::vector<CoverageSegment> 1104 buildSegments(MutableArrayRef<CountedRegion> Regions) { 1105 std::vector<CoverageSegment> Segments; 1106 SegmentBuilder Builder(Segments); 1107 1108 sortNestedRegions(Regions); 1109 ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions); 1110 1111 LLVM_DEBUG({ 1112 dbgs() << "Combined regions:\n"; 1113 for (const auto &CR : CombinedRegions) 1114 dbgs() << " " << CR.LineStart << ":" << CR.ColumnStart << " -> " 1115 << CR.LineEnd << ":" << CR.ColumnEnd 1116 << " (count=" << CR.ExecutionCount << ")\n"; 1117 }); 1118 1119 Builder.buildSegmentsImpl(CombinedRegions); 1120 1121 #ifndef NDEBUG 1122 for (unsigned I = 1, E = Segments.size(); I < E; ++I) { 1123 const auto &L = Segments[I - 1]; 1124 const auto &R = Segments[I]; 1125 if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) { 1126 if (L.Line == R.Line && L.Col == R.Col && !L.HasCount) 1127 continue; 1128 LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col 1129 << " followed by " << R.Line << ":" << R.Col << "\n"); 1130 assert(false && "Coverage segments not unique or sorted"); 1131 } 1132 } 1133 #endif 1134 1135 return Segments; 1136 } 1137 }; 1138 1139 } // end anonymous namespace 1140 1141 std::vector<StringRef> CoverageMapping::getUniqueSourceFiles() const { 1142 std::vector<StringRef> Filenames; 1143 for (const auto &Function : getCoveredFunctions()) 1144 llvm::append_range(Filenames, Function.Filenames); 1145 llvm::sort(Filenames); 1146 auto Last = std::unique(Filenames.begin(), Filenames.end()); 1147 Filenames.erase(Last, Filenames.end()); 1148 return Filenames; 1149 } 1150 1151 static SmallBitVector gatherFileIDs(StringRef SourceFile, 1152 const FunctionRecord &Function) { 1153 SmallBitVector FilenameEquivalence(Function.Filenames.size(), false); 1154 for (unsigned I = 0, E = Function.Filenames.size(); I < E; ++I) 1155 if (SourceFile == Function.Filenames[I]) 1156 FilenameEquivalence[I] = true; 1157 return FilenameEquivalence; 1158 } 1159 1160 /// Return the ID of the file where the definition of the function is located. 1161 static std::optional<unsigned> 1162 findMainViewFileID(const FunctionRecord &Function) { 1163 SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true); 1164 for (const auto &CR : Function.CountedRegions) 1165 if (CR.Kind == CounterMappingRegion::ExpansionRegion) 1166 IsNotExpandedFile[CR.ExpandedFileID] = false; 1167 int I = IsNotExpandedFile.find_first(); 1168 if (I == -1) 1169 return std::nullopt; 1170 return I; 1171 } 1172 1173 /// Check if SourceFile is the file that contains the definition of 1174 /// the Function. Return the ID of the file in that case or std::nullopt 1175 /// otherwise. 1176 static std::optional<unsigned> 1177 findMainViewFileID(StringRef SourceFile, const FunctionRecord &Function) { 1178 std::optional<unsigned> I = findMainViewFileID(Function); 1179 if (I && SourceFile == Function.Filenames[*I]) 1180 return I; 1181 return std::nullopt; 1182 } 1183 1184 static bool isExpansion(const CountedRegion &R, unsigned FileID) { 1185 return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID; 1186 } 1187 1188 CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const { 1189 CoverageData FileCoverage(Filename); 1190 std::vector<CountedRegion> Regions; 1191 1192 // Look up the function records in the given file. Due to hash collisions on 1193 // the filename, we may get back some records that are not in the file. 1194 ArrayRef<unsigned> RecordIndices = 1195 getImpreciseRecordIndicesForFilename(Filename); 1196 for (unsigned RecordIndex : RecordIndices) { 1197 const FunctionRecord &Function = Functions[RecordIndex]; 1198 auto MainFileID = findMainViewFileID(Filename, Function); 1199 auto FileIDs = gatherFileIDs(Filename, Function); 1200 for (const auto &CR : Function.CountedRegions) 1201 if (FileIDs.test(CR.FileID)) { 1202 Regions.push_back(CR); 1203 if (MainFileID && isExpansion(CR, *MainFileID)) 1204 FileCoverage.Expansions.emplace_back(CR, Function); 1205 } 1206 // Capture branch regions specific to the function (excluding expansions). 1207 for (const auto &CR : Function.CountedBranchRegions) 1208 if (FileIDs.test(CR.FileID) && (CR.FileID == CR.ExpandedFileID)) 1209 FileCoverage.BranchRegions.push_back(CR); 1210 // Capture MCDC records specific to the function. 1211 for (const auto &MR : Function.MCDCRecords) 1212 if (FileIDs.test(MR.getDecisionRegion().FileID)) 1213 FileCoverage.MCDCRecords.push_back(MR); 1214 } 1215 1216 LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n"); 1217 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions); 1218 1219 return FileCoverage; 1220 } 1221 1222 std::vector<InstantiationGroup> 1223 CoverageMapping::getInstantiationGroups(StringRef Filename) const { 1224 FunctionInstantiationSetCollector InstantiationSetCollector; 1225 // Look up the function records in the given file. Due to hash collisions on 1226 // the filename, we may get back some records that are not in the file. 1227 ArrayRef<unsigned> RecordIndices = 1228 getImpreciseRecordIndicesForFilename(Filename); 1229 for (unsigned RecordIndex : RecordIndices) { 1230 const FunctionRecord &Function = Functions[RecordIndex]; 1231 auto MainFileID = findMainViewFileID(Filename, Function); 1232 if (!MainFileID) 1233 continue; 1234 InstantiationSetCollector.insert(Function, *MainFileID); 1235 } 1236 1237 std::vector<InstantiationGroup> Result; 1238 for (auto &InstantiationSet : InstantiationSetCollector) { 1239 InstantiationGroup IG{InstantiationSet.first.first, 1240 InstantiationSet.first.second, 1241 std::move(InstantiationSet.second)}; 1242 Result.emplace_back(std::move(IG)); 1243 } 1244 return Result; 1245 } 1246 1247 CoverageData 1248 CoverageMapping::getCoverageForFunction(const FunctionRecord &Function) const { 1249 auto MainFileID = findMainViewFileID(Function); 1250 if (!MainFileID) 1251 return CoverageData(); 1252 1253 CoverageData FunctionCoverage(Function.Filenames[*MainFileID]); 1254 std::vector<CountedRegion> Regions; 1255 for (const auto &CR : Function.CountedRegions) 1256 if (CR.FileID == *MainFileID) { 1257 Regions.push_back(CR); 1258 if (isExpansion(CR, *MainFileID)) 1259 FunctionCoverage.Expansions.emplace_back(CR, Function); 1260 } 1261 // Capture branch regions specific to the function (excluding expansions). 1262 for (const auto &CR : Function.CountedBranchRegions) 1263 if (CR.FileID == *MainFileID) 1264 FunctionCoverage.BranchRegions.push_back(CR); 1265 1266 // Capture MCDC records specific to the function. 1267 for (const auto &MR : Function.MCDCRecords) 1268 if (MR.getDecisionRegion().FileID == *MainFileID) 1269 FunctionCoverage.MCDCRecords.push_back(MR); 1270 1271 LLVM_DEBUG(dbgs() << "Emitting segments for function: " << Function.Name 1272 << "\n"); 1273 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions); 1274 1275 return FunctionCoverage; 1276 } 1277 1278 CoverageData CoverageMapping::getCoverageForExpansion( 1279 const ExpansionRecord &Expansion) const { 1280 CoverageData ExpansionCoverage( 1281 Expansion.Function.Filenames[Expansion.FileID]); 1282 std::vector<CountedRegion> Regions; 1283 for (const auto &CR : Expansion.Function.CountedRegions) 1284 if (CR.FileID == Expansion.FileID) { 1285 Regions.push_back(CR); 1286 if (isExpansion(CR, Expansion.FileID)) 1287 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function); 1288 } 1289 for (const auto &CR : Expansion.Function.CountedBranchRegions) 1290 // Capture branch regions that only pertain to the corresponding expansion. 1291 if (CR.FileID == Expansion.FileID) 1292 ExpansionCoverage.BranchRegions.push_back(CR); 1293 1294 LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file " 1295 << Expansion.FileID << "\n"); 1296 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions); 1297 1298 return ExpansionCoverage; 1299 } 1300 1301 LineCoverageStats::LineCoverageStats( 1302 ArrayRef<const CoverageSegment *> LineSegments, 1303 const CoverageSegment *WrappedSegment, unsigned Line) 1304 : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line), 1305 LineSegments(LineSegments), WrappedSegment(WrappedSegment) { 1306 // Find the minimum number of regions which start in this line. 1307 unsigned MinRegionCount = 0; 1308 auto isStartOfRegion = [](const CoverageSegment *S) { 1309 return !S->IsGapRegion && S->HasCount && S->IsRegionEntry; 1310 }; 1311 for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I) 1312 if (isStartOfRegion(LineSegments[I])) 1313 ++MinRegionCount; 1314 1315 bool StartOfSkippedRegion = !LineSegments.empty() && 1316 !LineSegments.front()->HasCount && 1317 LineSegments.front()->IsRegionEntry; 1318 1319 HasMultipleRegions = MinRegionCount > 1; 1320 Mapped = 1321 !StartOfSkippedRegion && 1322 ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0)); 1323 1324 // if there is any starting segment at this line with a counter, it must be 1325 // mapped 1326 Mapped |= std::any_of( 1327 LineSegments.begin(), LineSegments.end(), 1328 [](const auto *Seq) { return Seq->IsRegionEntry && Seq->HasCount; }); 1329 1330 if (!Mapped) { 1331 return; 1332 } 1333 1334 // Pick the max count from the non-gap, region entry segments and the 1335 // wrapped count. 1336 if (WrappedSegment) 1337 ExecutionCount = WrappedSegment->Count; 1338 if (!MinRegionCount) 1339 return; 1340 for (const auto *LS : LineSegments) 1341 if (isStartOfRegion(LS)) 1342 ExecutionCount = std::max(ExecutionCount, LS->Count); 1343 } 1344 1345 LineCoverageIterator &LineCoverageIterator::operator++() { 1346 if (Next == CD.end()) { 1347 Stats = LineCoverageStats(); 1348 Ended = true; 1349 return *this; 1350 } 1351 if (Segments.size()) 1352 WrappedSegment = Segments.back(); 1353 Segments.clear(); 1354 while (Next != CD.end() && Next->Line == Line) 1355 Segments.push_back(&*Next++); 1356 Stats = LineCoverageStats(Segments, WrappedSegment, Line); 1357 ++Line; 1358 return *this; 1359 } 1360 1361 static std::string getCoverageMapErrString(coveragemap_error Err, 1362 const std::string &ErrMsg = "") { 1363 std::string Msg; 1364 raw_string_ostream OS(Msg); 1365 1366 switch (Err) { 1367 case coveragemap_error::success: 1368 OS << "success"; 1369 break; 1370 case coveragemap_error::eof: 1371 OS << "end of File"; 1372 break; 1373 case coveragemap_error::no_data_found: 1374 OS << "no coverage data found"; 1375 break; 1376 case coveragemap_error::unsupported_version: 1377 OS << "unsupported coverage format version"; 1378 break; 1379 case coveragemap_error::truncated: 1380 OS << "truncated coverage data"; 1381 break; 1382 case coveragemap_error::malformed: 1383 OS << "malformed coverage data"; 1384 break; 1385 case coveragemap_error::decompression_failed: 1386 OS << "failed to decompress coverage data (zlib)"; 1387 break; 1388 case coveragemap_error::invalid_or_missing_arch_specifier: 1389 OS << "`-arch` specifier is invalid or missing for universal binary"; 1390 break; 1391 } 1392 1393 // If optional error message is not empty, append it to the message. 1394 if (!ErrMsg.empty()) 1395 OS << ": " << ErrMsg; 1396 1397 return Msg; 1398 } 1399 1400 namespace { 1401 1402 // FIXME: This class is only here to support the transition to llvm::Error. It 1403 // will be removed once this transition is complete. Clients should prefer to 1404 // deal with the Error value directly, rather than converting to error_code. 1405 class CoverageMappingErrorCategoryType : public std::error_category { 1406 const char *name() const noexcept override { return "llvm.coveragemap"; } 1407 std::string message(int IE) const override { 1408 return getCoverageMapErrString(static_cast<coveragemap_error>(IE)); 1409 } 1410 }; 1411 1412 } // end anonymous namespace 1413 1414 std::string CoverageMapError::message() const { 1415 return getCoverageMapErrString(Err, Msg); 1416 } 1417 1418 const std::error_category &llvm::coverage::coveragemap_category() { 1419 static CoverageMappingErrorCategoryType ErrorCategory; 1420 return ErrorCategory; 1421 } 1422 1423 char CoverageMapError::ID = 0; 1424