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