LLVM: lib/ProfileData/Coverage/CoverageMapping.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

32#include

33#include

34#include

35#include

36#include

37#include

38#include

39#include

40#include

41#include

42#include <system_error>

43#include

44#include

45

46using namespace llvm;

48

49#define DEBUG_TYPE "coverage-mapping"

50

52 auto [It, Inserted] = ExpressionIndices.try_emplace(E, Expressions.size());

53 if (Inserted)

54 Expressions.push_back(E);

56}

57

58void CounterExpressionBuilder::extractTerms(Counter C, int Factor,

59 SmallVectorImpl &Terms) {

60 switch (C.getKind()) {

62 break;

65 break;

67 const auto &E = Expressions[C.getExpressionID()];

68 extractTerms(E.LHS, Factor, Terms);

69 extractTerms(

71 break;

72 }

73}

74

75Counter CounterExpressionBuilder::simplify(Counter ExpressionTree) {

76

78 extractTerms(ExpressionTree, +1, Terms);

79

80

81

82 if (Terms.size() == 0)

84

85

87 return LHS.CounterID < RHS.CounterID;

88 });

89

90

91 auto Prev = Terms.begin();

92 for (auto I = Prev + 1, E = Terms.end(); I != E; ++I) {

93 if (I->CounterID == Prev->CounterID) {

94 Prev->Factor += I->Factor;

95 continue;

96 }

97 ++Prev;

98 *Prev = *I;

99 }

100 Terms.erase(++Prev, Terms.end());

101

102 Counter C;

103

104

105 for (auto T : Terms) {

106 if (T.Factor <= 0)

107 continue;

108 for (int I = 0; I < T.Factor; ++I)

109 if (C.isZero())

111 else

114 }

115

116

117 for (auto T : Terms) {

118 if (T.Factor >= 0)

119 continue;

120 for (int I = 0; I < -T.Factor; ++I)

123 }

124 return C;

125}

126

129 return Simplify ? simplify(Cnt) : Cnt;

130}

131

133 bool Simplify) {

135 return Simplify ? simplify(Cnt) : Cnt;

136}

137

139

140 if (auto I = Map.find(C); I != Map.end())

141 return I->second;

142

143 if (C.isExpression())

144 return C;

145

146 auto CE = Expressions[C.getExpressionID()];

147 auto NewLHS = subst(CE.LHS, Map);

148 auto NewRHS = subst(CE.RHS, Map);

149

150

151 switch (CE.Kind) {

153 C = add(NewLHS, NewRHS);

154 break;

157 break;

158 }

159

160 return C;

161}

162

164 switch (C.getKind()) {

166 OS << '0';

167 return;

169 OS << '#' << C.getCounterID();

170 break;

172 if (C.getExpressionID() >= Expressions.size())

173 return;

174 const auto &E = Expressions[C.getExpressionID()];

175 OS << '(';

176 dump(E.LHS, OS);

178 dump(E.RHS, OS);

179 OS << ')';

180 break;

181 }

182 }

183 if (CounterValues.empty())

184 return;

186 if (auto E = Value.takeError()) {

188 return;

189 }

190 OS << '[' << *Value << ']';

191}

192

194 struct StackElem {

196 int64_t LHS = 0;

197 enum {

198 KNeverVisited = 0,

199 KVisitedOnce = 1,

200 KVisitedTwice = 2,

201 } VisitCount = KNeverVisited;

202 };

203

204 std::stack CounterStack;

205 CounterStack.push({C});

206

207 int64_t LastPoppedValue;

208

209 while (!CounterStack.empty()) {

210 StackElem &Current = CounterStack.top();

211

212 switch (Current.ICounter.getKind()) {

214 LastPoppedValue = 0;

215 CounterStack.pop();

216 break;

218 if (Current.ICounter.getCounterID() >= CounterValues.size())

220 LastPoppedValue = CounterValues[Current.ICounter.getCounterID()];

221 CounterStack.pop();

222 break;

224 if (Current.ICounter.getExpressionID() >= Expressions.size())

226 const auto &E = Expressions[Current.ICounter.getExpressionID()];

227 if (Current.VisitCount == StackElem::KNeverVisited) {

228 CounterStack.push(StackElem{E.LHS});

229 Current.VisitCount = StackElem::KVisitedOnce;

230 } else if (Current.VisitCount == StackElem::KVisitedOnce) {

231 Current.LHS = LastPoppedValue;

232 CounterStack.push(StackElem{E.RHS});

233 Current.VisitCount = StackElem::KVisitedTwice;

234 } else {

235 int64_t LHS = Current.LHS;

236 int64_t RHS = LastPoppedValue;

237 LastPoppedValue =

239 CounterStack.pop();

240 }

241 break;

242 }

243 }

244 }

245

246 return LastPoppedValue;

247}

248

249

250

251

252

254 if (IndependencePairs)

255 return;

256

257 IndependencePairs.emplace();

258

259 unsigned NumTVs = TV.size();

260

261 unsigned TVTrueIdx = std::distance(

262 TV.begin(),

264 [&](auto I) { return (I.second == MCDCRecord::MCDC_True); })

265

266 );

267 for (unsigned I = TVTrueIdx; I < NumTVs; ++I) {

268 const auto &[A, ACond] = TV[I];

270 for (unsigned J = 0; J < TVTrueIdx; ++J) {

271 const auto &[B, BCond] = TV[J];

273

274

275 auto AB = A.getDifferences(B);

276 if (AB.count() == 1)

277 IndependencePairs->insert(

278 {AB.find_first(), std::make_pair(J + 1, I + 1)});

279 }

280 }

281}

282

286

287 auto N = NextIDs.size();

289 for (unsigned ID = 0; ID < N; ++ID) {

290 for (unsigned C = 0; C < 2; ++C) {

291#ifndef NDEBUG

293#endif

294 auto NextID = NextIDs[ID][C];

295 Nodes[ID].NextIDs[C] = NextID;

296 if (NextID >= 0)

297 ++Nodes[NextID].InCount;

298 }

299 }

300

301

304 int,

305 unsigned

306 >>

307 Decisions;

308

309

311 assert(Nodes[0].InCount == 0);

312 Nodes[0].Width = 1;

314

315 unsigned Ord = 0;

316 while (!Q.empty()) {

317 auto IID = Q.begin();

318 int ID = *IID;

320 auto &Node = Nodes[ID];

322

323 for (unsigned I = 0; I < 2; ++I) {

324 auto NextID = Node.NextIDs[I];

325 assert(NextID != 0 && "NextID should not point to the top");

326 if (NextID < 0) {

327

328 Decisions.emplace_back(-Node.Width, Ord++, ID, I);

329 assert(Ord == Decisions.size());

330 continue;

331 }

332

333

334 auto &NextNode = Nodes[NextID];

335 assert(NextNode.InCount > 0);

336

337

340 auto NextWidth = int64_t(NextNode.Width) + Node.Width;

343 return;

344 }

345 NextNode.Width = NextWidth;

346

347

348

349 if (--NextNode.InCount == 0)

351 }

352 }

353

355

356

357 int64_t CurIdx = 0;

358 for (auto [NegWidth, Ord, ID, C] : Decisions) {

359 int Width = -NegWidth;

360 assert(Nodes[ID].Width == Width);

361 assert(Nodes[ID].NextIDs[C] < 0);

364 CurIdx += Width;

367 return;

368 }

369 }

370

373

374#ifndef NDEBUG

375 for (const auto &Idxs : Indices)

376 for (auto Idx : Idxs)

377 assert(Idx != INT_MIN);

379#endif

380}

381

382namespace {

383

384

385

386class NextIDsBuilder {

387protected:

389

390public:

392 : NextIDs(Branches.size()) {

393#ifndef NDEBUG

395#endif

396 for (const auto *Branch : Branches) {

397 const auto &BranchParams = Branch->getBranchParams();

398 assert(SeenIDs.insert(BranchParams.ID).second && "Duplicate CondID");

399 NextIDs[BranchParams.ID] = BranchParams.Conds;

400 }

401 assert(SeenIDs.size() == Branches.size());

402 }

403};

404

406

407

408

409

411

412

415

416

417

419

420

421 unsigned NumConditions;

422

423

425

426

428

429

430

431 std::array<MCDCRecord::TestVectors, 2> ExecVectorsByCond;

432

433

434

436

437#ifndef NDEBUG

439#endif

440

441 bool IsVersion11;

442

443public:

444 MCDCRecordProcessor(const BitVector &Bitmap,

447 bool IsVersion11)

448 : NextIDsBuilder(Branches), TVIdxBuilder(this->NextIDs), Bitmap(Bitmap),

450 Branches(Branches), NumConditions(DecisionParams.NumConditions),

452 IndependencePairs(NumConditions), ExecVectors(ExecVectorsByCond[false]),

453 IsVersion11(IsVersion11) {}

454

455private:

456

457

458

460 int TVIdx) {

464 TV.set(ID, MCDCCond);

465 auto NextID = NextIDs[ID][MCDCCond];

466 auto NextTVIdx = TVIdx + Indices[ID][MCDCCond];

467 assert(NextID == SavedNodes[ID].NextIDs[MCDCCond]);

468 if (NextID >= 0) {

469 buildTestVector(TV, NextID, NextTVIdx);

470 continue;

471 }

472

473 assert(TVIdx < SavedNodes[ID].Width);

474 assert(TVIdxs.insert(NextTVIdx).second && "Duplicate TVIdx");

475

476 if (!Bitmap[IsVersion11

477 ? DecisionParams.BitmapIdx * CHAR_BIT + TV.getIndex()

478 : DecisionParams.BitmapIdx - NumTestVectors + NextTVIdx])

479 continue;

480

481

482

483

484 ExecVectorsByCond[MCDCCond].push_back({TV, MCDCCond});

485 }

486

487

489 }

490

491

492

493 void findExecutedTestVectors() {

494

495

496

497

498 MCDCRecord::TestVector TV(NumConditions);

499 buildTestVector(TV, 0, 0);

500 assert(TVIdxs.size() == unsigned(NumTestVectors) &&

501 "TVIdxs wasn't fulfilled");

502

503

504

505

506 auto &ExecVectorsT = ExecVectorsByCond[true];

507 ExecVectors.append(std::make_move_iterator(ExecVectorsT.begin()),

508 std::make_move_iterator(ExecVectorsT.end()));

509 }

510

511public:

512

513

514

515

516

517

518

519

520

521 MCDCRecord processMCDCRecord() {

524

525

526

527

528

529

530

531

532

533

534

535 for (auto [I, B] : enumerate(Branches)) {

536 const auto &BranchParams = B->getBranchParams();

537 PosToID[I] = BranchParams.ID;

538 CondLoc[I] = B->startLoc();

539 Folded[false][I] = B->FalseCount.isZero();

540 Folded[true][I] = B->Count.isZero();

541 }

542

543

544 findExecutedTestVectors();

545

546

547 return MCDCRecord(Region, std::move(ExecVectors), std::move(Folded),

548 std::move(PosToID), std::move(CondLoc));

549 }

550};

551

552}

553

557

558 MCDCRecordProcessor MCDCProcessor(Bitmap, Region, Branches, IsVersion11);

559 return MCDCProcessor.processMCDCRecord();

560}

561

563 struct StackElem {

565 int64_t LHS = 0;

566 enum {

567 KNeverVisited = 0,

568 KVisitedOnce = 1,

569 KVisitedTwice = 2,

570 } VisitCount = KNeverVisited;

571 };

572

573 std::stack CounterStack;

574 CounterStack.push({C});

575

576 int64_t LastPoppedValue;

577

578 while (!CounterStack.empty()) {

579 StackElem &Current = CounterStack.top();

580

581 switch (Current.ICounter.getKind()) {

583 LastPoppedValue = 0;

584 CounterStack.pop();

585 break;

587 LastPoppedValue = Current.ICounter.getCounterID();

588 CounterStack.pop();

589 break;

591 if (Current.ICounter.getExpressionID() >= Expressions.size()) {

592 LastPoppedValue = 0;

593 CounterStack.pop();

594 } else {

595 const auto &E = Expressions[Current.ICounter.getExpressionID()];

596 if (Current.VisitCount == StackElem::KNeverVisited) {

597 CounterStack.push(StackElem{E.LHS});

598 Current.VisitCount = StackElem::KVisitedOnce;

599 } else if (Current.VisitCount == StackElem::KVisitedOnce) {

600 Current.LHS = LastPoppedValue;

601 CounterStack.push(StackElem{E.RHS});

602 Current.VisitCount = StackElem::KVisitedTwice;

603 } else {

604 int64_t LHS = Current.LHS;

605 int64_t RHS = LastPoppedValue;

606 LastPoppedValue = std::max(LHS, RHS);

607 CounterStack.pop();

608 }

609 }

610 break;

611 }

612 }

613 }

614

615 return LastPoppedValue;

616}

617

618void FunctionRecordIterator::skipOtherFiles() {

619 while (Current != Records.end() && !Filename.empty() &&

620 Filename != Current->Filenames[0])

621 advanceOne();

622 if (Current == Records.end())

624}

625

626ArrayRef CoverageMapping::getImpreciseRecordIndicesForFilename(

628 size_t FilenameHash = hash_value(Filename);

629 auto RecordIt = FilenameHash2RecordIndices.find(FilenameHash);

630 if (RecordIt == FilenameHash2RecordIndices.end())

631 return {};

632 return RecordIt->second;

633}

634

637 unsigned MaxCounterID = 0;

638 for (const auto &Region : Record.MappingRegions) {

639 MaxCounterID = std::max(MaxCounterID, Ctx.getMaxCounterID(Region.Count));

640 }

641 return MaxCounterID;

642}

643

644

646 bool IsVersion11) {

647 unsigned MaxBitmapIdx = 0;

648 unsigned NumConditions = 0;

649

650

651

654 continue;

655 const auto &DecisionParams = Region.getDecisionParams();

656 if (MaxBitmapIdx <= DecisionParams.BitmapIdx) {

657 MaxBitmapIdx = DecisionParams.BitmapIdx;

658 NumConditions = DecisionParams.NumConditions;

659 }

660 }

661

662 if (IsVersion11)

663 MaxBitmapIdx = MaxBitmapIdx * CHAR_BIT +

665

666 return MaxBitmapIdx;

667}

668

669namespace {

670

671

672class MCDCDecisionRecorder {

673private:

674

675

676

677

678 struct DecisionRecord {

679 const CounterMappingRegion *DecisionRegion;

680

681

682 mcdc::DecisionParameters DecisionParams;

685

686

687

689

690

691

693

694

695

696

697

698 DenseSet ExpandedFileIDs;

699

700 DecisionRecord(const CounterMappingRegion &Decision)

701 : DecisionRegion(&Decision),

702 DecisionParams(Decision.getDecisionParams()),

703 DecisionStartLoc(Decision.startLoc()),

704 DecisionEndLoc(Decision.endLoc()) {

706 }

707

708

709 bool dominates(const CounterMappingRegion &R) const {

710

711 if (R.FileID == DecisionRegion->FileID &&

712 R.startLoc() >= DecisionStartLoc && R.endLoc() <= DecisionEndLoc)

713 return true;

714

715

716 return ExpandedFileIDs.contains(R.FileID);

717 }

718

720 NotProcessed = 0,

721 Processed,

722 Completed,

723 };

724

725

726

727

728 Result addBranch(const CounterMappingRegion &Branch) {

730

732

735 return NotProcessed;

736

738 return NotProcessed;

739

741

742

743

744 if (ConditionID == 0)

745 MCDCBranches.insert(MCDCBranches.begin(), &Branch);

746 else

748

749

751

752

753 return (MCDCBranches.size() == DecisionParams.NumConditions ? Completed

754 : Processed);

755 }

756

757

758

759

760 bool recordExpansion(const CounterMappingRegion &Expansion) {

762 return false;

763

765 return true;

766 }

767 };

768

769private:

770

771

772

774

775public:

776 ~MCDCDecisionRecorder() {

777 assert(Decisions.empty() && "All Decisions have not been resolved");

778 }

779

780

781 void registerDecision(const CounterMappingRegion &Decision) {

783 }

784

785 void recordExpansion(const CounterMappingRegion &Expansion) {

787 return Decision.recordExpansion(Expansion);

788 });

789 }

790

791 using DecisionAndBranches =

792 std::pair<const CounterMappingRegion *,

794 >;

795

796

797

798

799

800 std::optional

801 processBranch(const CounterMappingRegion &Branch) {

802

803 for (auto DecisionIter = Decisions.begin(), DecisionEnd = Decisions.end();

804 DecisionIter != DecisionEnd; ++DecisionIter)

805 switch (DecisionIter->addBranch(Branch)) {

806 case DecisionRecord::NotProcessed:

807 continue;

808 case DecisionRecord::Processed:

809 return std::nullopt;

810 case DecisionRecord::Completed:

811 DecisionAndBranches Result =

812 std::make_pair(DecisionIter->DecisionRegion,

813 std::move(DecisionIter->MCDCBranches));

814 Decisions.erase(DecisionIter);

816 }

817

819 }

820};

821

822}

823

824Error CoverageMapping::loadFunctionRecord(

825 const CoverageMappingRecord &Record,

826 const std::optional<std::reference_wrapper>

827 &ProfileReader) {

828 StringRef OrigFuncName = Record.FunctionName;

829 if (OrigFuncName.empty())

831 "record function name is empty");

832

835 else

837

838 CounterMappingContext Ctx(Record.Expressions);

839

840 std::vector<uint64_t> Counts;

841 if (ProfileReader) {

842 if (Error E = ProfileReader.value().get().getFunctionCounts(

846 FuncHashMismatches.emplace_back(std::string(Record.FunctionName),

849 }

853 }

854 } else {

856 }

857 Ctx.setCounts(Counts);

858

859 bool IsVersion11 =

860 ProfileReader && ProfileReader.value().get().getVersion() <

862

863 BitVector Bitmap;

864 if (ProfileReader) {

865 if (Error E = ProfileReader.value().get().getFunctionBitmap(

869 FuncHashMismatches.emplace_back(std::string(Record.FunctionName),

872 }

876 }

877 } else {

879 }

880 Ctx.setBitmap(std::move(Bitmap));

881

883

884

885

886

887

888

890 Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)

892

893 MCDCDecisionRecorder MCDCDecisions;

896

897

899 MCDCDecisions.registerDecision(Region);

900 continue;

901 }

902 Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);

903 if (auto E = ExecutionCount.takeError()) {

906 }

907 Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);

908 if (auto E = AltExecutionCount.takeError()) {

911 }

912 Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);

913

914

916 MCDCDecisions.recordExpansion(Region);

917 continue;

918 }

919

920

922 continue;

923

924 auto Result = MCDCDecisions.processBranch(Region);

925 if (!Result)

926 continue;

927

928 auto MCDCDecision = Result->first;

929 auto &MCDCBranches = Result->second;

930

931

932

933

934 Expected Record =

935 Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);

939 }

940

941

942 Function.pushMCDCRecord(std::move(*Record));

943 }

944

945

947 if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)

949

950 Functions.push_back(std::move(Function));

951

952

953

954

955 unsigned RecordIndex = Functions.size() - 1;

956 for (StringRef Filename : Record.Filenames) {

957 auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];

958

959

960

961 if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)

962 RecordIndices.push_back(RecordIndex);

963 }

964

966}

967

968

969

970Error CoverageMapping::loadFromReaders(

971 ArrayRef<std::unique_ptr> CoverageReaders,

972 std::optional<std::reference_wrapper>

973 &ProfileReader,

974 CoverageMapping &Coverage) {

975 assert(Coverage.SingleByteCoverage || !ProfileReader ||

976 *Coverage.SingleByteCoverage ==

977 ProfileReader.value().get().hasSingleByteCoverage());

978 Coverage.SingleByteCoverage =

979 !ProfileReader || ProfileReader.value().get().hasSingleByteCoverage();

980 for (const auto &CoverageReader : CoverageReaders) {

981 for (auto RecordOrErr : *CoverageReader) {

982 if (Error E = RecordOrErr.takeError())

983 return E;

984 const auto &Record = *RecordOrErr;

985 if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))

986 return E;

987 }

988 }

990}

991

993 ArrayRef<std::unique_ptr> CoverageReaders,

994 std::optional<std::reference_wrapper>

995 &ProfileReader) {

996 auto Coverage = std::unique_ptr(new CoverageMapping());

997 if (Error E = loadFromReaders(CoverageReaders, ProfileReader, *Coverage))

998 return std::move(E);

999 return std::move(Coverage);

1000}

1001

1002

1010

1011Error CoverageMapping::loadFromFile(

1012 StringRef Filename, StringRef Arch, StringRef CompilationDir,

1013 std::optional<std::reference_wrapper>

1014 &ProfileReader,

1015 CoverageMapping &Coverage, bool &DataFound,

1016 SmallVectorImplobject::BuildID *FoundBinaryIDs) {

1018 Filename, false, false);

1019 if (std::error_code EC = CovMappingBufOrErr.getError())

1021 MemoryBufferRef CovMappingBufRef =

1022 CovMappingBufOrErr.get()->getMemBufferRef();

1024

1027 CovMappingBufRef, Arch, Buffers, CompilationDir,

1028 FoundBinaryIDs ? &BinaryIDs : nullptr);

1029 if (Error E = CoverageReadersOrErr.takeError()) {

1031 if (E)

1033 return E;

1034 }

1035

1037 for (auto &Reader : CoverageReadersOrErr.get())

1038 Readers.push_back(std::move(Reader));

1039 if (FoundBinaryIDs && !Readers.empty()) {

1043 }));

1044 }

1045 DataFound |= !Readers.empty();

1046 if (Error E = loadFromReaders(Readers, ProfileReader, Coverage))

1049}

1050

1053 std::optional ProfileFilename, vfs::FileSystem &FS,

1056 std::unique_ptr ProfileReader;

1057 if (ProfileFilename) {

1058 auto ProfileReaderOrErr =

1060 if (Error E = ProfileReaderOrErr.takeError())

1061 return createFileError(ProfileFilename.value(), std::move(E));

1062 ProfileReader = std::move(ProfileReaderOrErr.get());

1063 }

1064 auto ProfileReaderRef =

1065 ProfileReader

1066 ? std::optional<std::reference_wrapper>(

1067 *ProfileReader)

1068 : std::nullopt;

1069 auto Coverage = std::unique_ptr(new CoverageMapping());

1070 bool DataFound = false;

1071

1072 auto GetArch = [&](size_t Idx) {

1073 if (Arches.empty())

1075 if (Arches.size() == 1)

1076 return Arches.front();

1077 return Arches[Idx];

1078 };

1079

1081 for (const auto &File : llvm::enumerate(ObjectFilenames)) {

1082 if (Error E = loadFromFile(File.value(), GetArch(File.index()),

1083 CompilationDir, ProfileReaderRef, *Coverage,

1084 DataFound, &FoundBinaryIDs))

1085 return std::move(E);

1086 }

1087

1088 if (BIDFetcher) {

1089 std::vectorobject::BuildID ProfileBinaryIDs;

1090 if (ProfileReader)

1091 if (Error E = ProfileReader->readBinaryIds(ProfileBinaryIDs))

1092 return createFileError(ProfileFilename.value(), std::move(E));

1093

1095 if (!ProfileBinaryIDs.empty()) {

1097 return std::lexicographical_compare(A.begin(), A.end(), B.begin(),

1098 B.end());

1099 };

1100 llvm::sort(FoundBinaryIDs, Compare);

1101 std::set_difference(

1102 ProfileBinaryIDs.begin(), ProfileBinaryIDs.end(),

1103 FoundBinaryIDs.begin(), FoundBinaryIDs.end(),

1104 std::inserter(BinaryIDsToFetch, BinaryIDsToFetch.end()), Compare);

1105 }

1106

1108 std::optionalstd::string PathOpt = BIDFetcher->fetch(BinaryID);

1109 if (PathOpt) {

1110 std::string Path = std::move(*PathOpt);

1112 if (Error E = loadFromFile(Path, Arch, CompilationDir, ProfileReaderRef,

1113 *Coverage, DataFound))

1114 return std::move(E);

1115 } else if (CheckBinaryIDs) {

1117 ProfileFilename.value(),

1119 "Missing binary ID: " +

1120 llvm::toHex(BinaryID, true)));

1121 }

1122 }

1123 }

1124

1125 if (!DataFound)

1127 join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "),

1129 return std::move(Coverage);

1130}

1131

1132namespace {

1133

1134

1135

1136

1137

1138class FunctionInstantiationSetCollector {

1139 using MapT = std::map<LineColPair, std::vector<const FunctionRecord *>>;

1140 MapT InstantiatedFunctions;

1141

1142public:

1145 while (I != E && I->FileID != FileID)

1146 ++I;

1147 assert(I != E && "function does not cover the given file");

1148 auto &Functions = InstantiatedFunctions[I->startLoc()];

1149 Functions.push_back(&Function);

1150 }

1151

1152 MapT::iterator begin() { return InstantiatedFunctions.begin(); }

1153 MapT::iterator end() { return InstantiatedFunctions.end(); }

1154};

1155

1156class SegmentBuilder {

1157 std::vector &Segments;

1159

1160 SegmentBuilder(std::vector &Segments) : Segments(Segments) {}

1161

1162

1163

1164

1165

1166 void startSegment(const CountedRegion &Region, LineColPair StartLoc,

1167 bool IsRegionEntry, bool EmitSkippedRegion = false) {

1168 bool HasCount = !EmitSkippedRegion &&

1170

1171

1172 if (Segments.empty() && !IsRegionEntry && !EmitSkippedRegion) {

1174 if (Last.HasCount == HasCount && Last.Count == Region.ExecutionCount &&

1175 Last.IsRegionEntry)

1176 return;

1177 }

1178

1179 if (HasCount)

1180 Segments.emplace_back(StartLoc.first, StartLoc.second,

1181 Region.ExecutionCount, IsRegionEntry,

1183 else

1184 Segments.emplace_back(StartLoc.first, StartLoc.second, IsRegionEntry);

1185

1188 dbgs() << "Segment at " << Last.Line << ":" << Last.Col

1189 << " (count = " << Last.Count << ")"

1190 << (Last.IsRegionEntry ? ", RegionEntry" : "")

1191 << (Last.HasCount ? ", Skipped" : "")

1192 << (Last.IsGapRegion ? ", Gap" : "") << "\n";

1193 });

1194 }

1195

1196

1197

1198

1199

1200

1201 void completeRegionsUntil(std::optional Loc,

1202 unsigned FirstCompletedRegion) {

1203

1204

1205 auto CompletedRegionsIt = ActiveRegions.begin() + FirstCompletedRegion;

1206 std::stable_sort(CompletedRegionsIt, ActiveRegions.end(),

1207 [](const CountedRegion *L, const CountedRegion *R) {

1208 return L->endLoc() < R->endLoc();

1209 });

1210

1211

1212 for (unsigned I = FirstCompletedRegion + 1, E = ActiveRegions.size(); I < E;

1213 ++I) {

1214 const auto *CompletedRegion = ActiveRegions[I];

1215 assert((!Loc || CompletedRegion->endLoc() <= *Loc) &&

1216 "Completed region ends after start of new region");

1217

1218 const auto *PrevCompletedRegion = ActiveRegions[I - 1];

1219 auto CompletedSegmentLoc = PrevCompletedRegion->endLoc();

1220

1221

1222 if (Loc && CompletedSegmentLoc == *Loc)

1223 break;

1224

1225

1226

1227 if (CompletedSegmentLoc == CompletedRegion->endLoc())

1228 continue;

1229

1230

1231 for (unsigned J = I + 1; J < E; ++J)

1232 if (CompletedRegion->endLoc() == ActiveRegions[J]->endLoc())

1233 CompletedRegion = ActiveRegions[J];

1234

1235 startSegment(*CompletedRegion, CompletedSegmentLoc, false);

1236 }

1237

1238 auto Last = ActiveRegions.back();

1239 if (FirstCompletedRegion && Last->endLoc() != *Loc) {

1240

1241

1242 startSegment(*ActiveRegions[FirstCompletedRegion - 1], Last->endLoc(),

1243 false);

1244 } else if (!FirstCompletedRegion && (!Loc || *Loc != Last->endLoc())) {

1245

1246

1247 startSegment(*Last, Last->endLoc(), false, true);

1248 }

1249

1250

1251 ActiveRegions.erase(CompletedRegionsIt, ActiveRegions.end());

1252 }

1253

1255 for (const auto &CR : enumerate(Regions)) {

1256 auto CurStartLoc = CR.value().startLoc();

1257

1258

1259 auto CompletedRegions =

1260 std::stable_partition(ActiveRegions.begin(), ActiveRegions.end(),

1261 [&](const CountedRegion *Region) {

1262 return !(Region->endLoc() <= CurStartLoc);

1263 });

1264 if (CompletedRegions != ActiveRegions.end()) {

1265 unsigned FirstCompletedRegion =

1266 std::distance(ActiveRegions.begin(), CompletedRegions);

1267 completeRegionsUntil(CurStartLoc, FirstCompletedRegion);

1268 }

1269

1271

1272

1273 if (CurStartLoc == CR.value().endLoc()) {

1274

1275

1277 (CR.index() + 1) == Regions.size() ||

1279 startSegment(ActiveRegions.empty() ? CR.value() : *ActiveRegions.back(),

1280 CurStartLoc, !GapRegion, Skipped);

1281

1282

1283 if (Skipped && !ActiveRegions.empty())

1284 startSegment(*ActiveRegions.back(), CurStartLoc, false);

1285 continue;

1286 }

1287 if (CR.index() + 1 == Regions.size() ||

1288 CurStartLoc != Regions[CR.index() + 1].startLoc()) {

1289

1290

1291 startSegment(CR.value(), CurStartLoc, !GapRegion);

1292 }

1293

1294

1295 ActiveRegions.push_back(&CR.value());

1296 }

1297

1298

1299 if (!ActiveRegions.empty())

1300 completeRegionsUntil(std::nullopt, 0);

1301 }

1302

1303

1305 llvm::sort(Regions, [](const CountedRegion &LHS, const CountedRegion &RHS) {

1306 if (LHS.startLoc() != RHS.startLoc())

1307 return LHS.startLoc() < RHS.startLoc();

1308 if (LHS.endLoc() != RHS.endLoc())

1309

1310 return RHS.endLoc() < LHS.endLoc();

1311

1312

1313

1314

1315

1320 "Unexpected order of region kind values");

1321 return LHS.Kind < RHS.Kind;

1322 });

1323 }

1324

1325

1328 if (Regions.empty())

1329 return Regions;

1331 auto End = Regions.end();

1332 for (auto I = Regions.begin() + 1; I != End; ++I) {

1333 if (Active->startLoc() != I->startLoc() ||

1334 Active->endLoc() != I->endLoc()) {

1335

1337 if (Active != I)

1339 continue;

1340 }

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350

1351

1352

1353 if (I->Kind == Active->Kind)

1354 Active->ExecutionCount += I->ExecutionCount;

1355 }

1356 return Regions.drop_back(std::distance(++Active, End));

1357 }

1358

1359public:

1360

1361 static std::vector

1363 std::vector Segments;

1364 SegmentBuilder Builder(Segments);

1365

1366 sortNestedRegions(Regions);

1368

1370 dbgs() << "Combined regions:\n";

1371 for (const auto &CR : CombinedRegions)

1372 dbgs() << " " << CR.LineStart << ":" << CR.ColumnStart << " -> "

1373 << CR.LineEnd << ":" << CR.ColumnEnd

1374 << " (count=" << CR.ExecutionCount << ")\n";

1375 });

1376

1377 Builder.buildSegmentsImpl(CombinedRegions);

1378

1379#ifndef NDEBUG

1380 for (unsigned I = 1, E = Segments.size(); I < E; ++I) {

1383 if (!(L.Line < R.Line) && !(L.Line == R.Line && L.Col < R.Col)) {

1384 if (L.Line == R.Line && L.Col == R.Col && L.HasCount)

1385 continue;

1386 LLVM_DEBUG(dbgs() << " ! Segment " << L.Line << ":" << L.Col

1387 << " followed by " << R.Line << ":" << R.Col << "\n");

1388 assert(false && "Coverage segments not unique or sorted");

1389 }

1390 }

1391#endif

1392

1394 }

1395};

1396

1397}

1398

1400 std::vector Filenames;

1405 Filenames.erase(Last, Filenames.end());

1406 return Filenames;

1407}

1408

1413 if (SourceFile == Function.Filenames[I])

1414 FilenameEquivalence[I] = true;

1415 return FilenameEquivalence;

1416}

1417

1418

1419static std::optional

1422 for (const auto &CR : Function.CountedRegions)

1424 IsNotExpandedFile[CR.ExpandedFileID] = false;

1426 if (I == -1)

1427 return std::nullopt;

1428 return I;

1429}

1430

1431

1432

1433

1434static std::optional

1437 if (I && SourceFile == Function.Filenames[*I])

1438 return I;

1439 return std::nullopt;

1440}

1441

1445

1447 assert(SingleByteCoverage);

1448 CoverageData FileCoverage(*SingleByteCoverage, Filename);

1449 std::vector Regions;

1450

1451

1452

1454 getImpreciseRecordIndicesForFilename(Filename);

1455 for (unsigned RecordIndex : RecordIndices) {

1459 for (const auto &CR : Function.CountedRegions)

1460 if (FileIDs.test(CR.FileID)) {

1461 Regions.push_back(CR);

1462 if (MainFileID && isExpansion(CR, *MainFileID))

1463 FileCoverage.Expansions.emplace_back(CR, Function);

1464 }

1465

1466 for (const auto &CR : Function.CountedBranchRegions)

1467 if (FileIDs.test(CR.FileID))

1468 FileCoverage.BranchRegions.push_back(CR);

1469

1470 for (const auto &MR : Function.MCDCRecords)

1471 if (FileIDs.test(MR.getDecisionRegion().FileID))

1472 FileCoverage.MCDCRecords.push_back(MR);

1473 }

1474

1475 LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");

1476 FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);

1477

1478 return FileCoverage;

1479}

1480

1481std::vector

1483 FunctionInstantiationSetCollector InstantiationSetCollector;

1484

1485

1487 getImpreciseRecordIndicesForFilename(Filename);

1488 for (unsigned RecordIndex : RecordIndices) {

1491 if (!MainFileID)

1492 continue;

1493 InstantiationSetCollector.insert(Function, *MainFileID);

1494 }

1495

1496 std::vector Result;

1497 for (auto &InstantiationSet : InstantiationSetCollector) {

1499 InstantiationSet.first.second,

1500 std::move(InstantiationSet.second)};

1501 Result.emplace_back(std::move(IG));

1502 }

1503 return Result;

1504}

1505

1509 if (!MainFileID)

1511

1512 assert(SingleByteCoverage);

1513 CoverageData FunctionCoverage(*SingleByteCoverage,

1514 Function.Filenames[*MainFileID]);

1515 std::vector Regions;

1516 for (const auto &CR : Function.CountedRegions)

1517 if (CR.FileID == *MainFileID) {

1518 Regions.push_back(CR);

1520 FunctionCoverage.Expansions.emplace_back(CR, Function);

1521 }

1522

1523 for (const auto &CR : Function.CountedBranchRegions)

1524 if (CR.FileID == *MainFileID)

1525 FunctionCoverage.BranchRegions.push_back(CR);

1526

1527

1528 for (const auto &MR : Function.MCDCRecords)

1529 if (MR.getDecisionRegion().FileID == *MainFileID)

1530 FunctionCoverage.MCDCRecords.push_back(MR);

1531

1533 << "\n");

1534 FunctionCoverage.Segments = SegmentBuilder::buildSegments(Regions);

1535

1536 return FunctionCoverage;

1537}

1538

1541 assert(SingleByteCoverage);

1543 *SingleByteCoverage, Expansion.Function.Filenames[Expansion.FileID]);

1544 std::vector Regions;

1545 for (const auto &CR : Expansion.Function.CountedRegions)

1546 if (CR.FileID == Expansion.FileID) {

1547 Regions.push_back(CR);

1549 ExpansionCoverage.Expansions.emplace_back(CR, Expansion.Function);

1550 }

1551 for (const auto &CR : Expansion.Function.CountedBranchRegions)

1552

1553 if (CR.FileID == Expansion.FileID)

1554 ExpansionCoverage.BranchRegions.push_back(CR);

1555

1556 LLVM_DEBUG(dbgs() << "Emitting segments for expansion of file "

1558 ExpansionCoverage.Segments = SegmentBuilder::buildSegments(Regions);

1559

1560 return ExpansionCoverage;

1561}

1562

1563LineCoverageStats::LineCoverageStats(

1566 : ExecutionCount(0), HasMultipleRegions(false), Mapped(false), Line(Line),

1567 LineSegments(LineSegments), WrappedSegment(WrappedSegment) {

1568

1569 unsigned MinRegionCount = 0;

1571 return !S->IsGapRegion && S->HasCount && S->IsRegionEntry;

1572 };

1573 for (unsigned I = 0; I < LineSegments.size() && MinRegionCount < 2; ++I)

1574 if (isStartOfRegion(LineSegments[I]))

1575 ++MinRegionCount;

1576

1577 bool StartOfSkippedRegion = !LineSegments.empty() &&

1578 !LineSegments.front()->HasCount &&

1579 LineSegments.front()->IsRegionEntry;

1580

1581 HasMultipleRegions = MinRegionCount > 1;

1582 Mapped =

1583 !StartOfSkippedRegion &&

1584 ((WrappedSegment && WrappedSegment->HasCount) || (MinRegionCount > 0));

1585

1586

1587

1588 Mapped |= any_of(LineSegments, [](const auto *Seq) {

1589 return Seq->IsRegionEntry && Seq->HasCount;

1590 });

1591

1592 if (!Mapped) {

1593 return;

1594 }

1595

1596

1597

1598 if (WrappedSegment)

1599 ExecutionCount = WrappedSegment->Count;

1600 if (!MinRegionCount)

1601 return;

1602 for (const auto *LS : LineSegments)

1603 if (isStartOfRegion(LS))

1604 ExecutionCount = std::max(ExecutionCount, LS->Count);

1605}

1606

1608 if (Next == CD.end()) {

1610 Ended = true;

1611 return *this;

1612 }

1613 if (Segments.size())

1614 WrappedSegment = Segments.back();

1615 Segments.clear();

1616 while (Next != CD.end() && Next->Line == Line)

1617 Segments.push_back(&*Next++);

1619 ++Line;

1620 return *this;

1621}

1622

1624 const std::string &ErrMsg = "") {

1625 std::string Msg;

1627

1628 switch (Err) {

1630 OS << "success";

1631 break;

1633 OS << "end of File";

1634 break;

1636 OS << "no coverage data found";

1637 break;

1639 OS << "unsupported coverage format version";

1640 break;

1642 OS << "truncated coverage data";

1643 break;

1645 OS << "malformed coverage data";

1646 break;

1648 OS << "failed to decompress coverage data (zlib)";

1649 break;

1651 OS << "`-arch` specifier is invalid or missing for universal binary";

1652 break;

1653 }

1654

1655

1656 if (!ErrMsg.empty())

1657 OS << ": " << ErrMsg;

1658

1659 return Msg;

1660}

1661

1662namespace {

1663

1664

1665

1666

1667class CoverageMappingErrorCategoryType : public std::error_category {

1668 const char *name() const noexcept override { return "llvm.coveragemap"; }

1669 std::string message(int IE) const override {

1671 }

1672};

1673

1674}

1675

1679

1681 static CoverageMappingErrorCategoryType ErrorCategory;

1682 return ErrorCategory;

1683}

1684

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

This file declares a library for handling Build IDs and using them to find debug info.

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

static SmallBitVector gatherFileIDs(StringRef SourceFile, const FunctionRecord &Function)

Definition CoverageMapping.cpp:1409

static std::optional< unsigned > findMainViewFileID(const FunctionRecord &Function)

Return the ID of the file where the definition of the function is located.

Definition CoverageMapping.cpp:1420

static bool isExpansion(const CountedRegion &R, unsigned FileID)

Definition CoverageMapping.cpp:1442

static Error handleMaybeNoDataFoundError(Error E)

Definition CoverageMapping.cpp:1003

static unsigned getMaxBitmapSize(const CoverageMappingRecord &Record, bool IsVersion11)

Returns the bit count.

Definition CoverageMapping.cpp:645

static std::string getCoverageMapErrString(coveragemap_error Err, const std::string &ErrMsg="")

Definition CoverageMapping.cpp:1623

static unsigned getMaxCounterID(const CounterMappingContext &Ctx, const CoverageMappingRecord &Record)

Definition CoverageMapping.cpp:635

This file defines the DenseMap class.

static bool dominates(InstrPosIndexes &PosIndexes, const MachineInstr &A, const MachineInstr &B)

This file implements the SmallBitVector class.

This file defines the SmallVector class.

Defines the virtual file system interface vfs::FileSystem.

ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...

const T & front() const

front - Get the first element.

size_t size() const

size - Get the array size.

bool empty() const

empty - Check if the array is empty.

Implements a dense probed hash-table based set.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")

Factory method to create an indexed reader.

static std::pair< instrprof_error, std::string > take(Error E)

Consume an Error and return the raw enum value contained within it, and the optional error message.

static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileOrSTDIN(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, std::optional< Align > Alignment=std::nullopt)

Open the specified file as a MemoryBuffer, or open stdin if the Filename is "-".

MutableArrayRef< T > drop_back(size_t N=1) const

This is a 'bitvector' (really, a variable-sized bit array), optimized for the case when the array is ...

int find_first() const

Returns the index of the first set bit, -1 if none of the bits are set.

This class consists of common code factored out of the SmallVector class to reduce code duplication b...

reference emplace_back(ArgTypes &&... Args)

iterator erase(const_iterator CI)

iterator insert(iterator I, T &&Elt)

void push_back(const T &Elt)

This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.

StringRef - Represent a constant reference to a string, i.e.

constexpr bool empty() const

empty - Check if the string is empty.

LLVM Value Representation.

static Expected< std::vector< std::unique_ptr< BinaryCoverageReader > > > create(MemoryBufferRef ObjectBuffer, StringRef Arch, SmallVectorImpl< std::unique_ptr< MemoryBuffer > > &ObjectFileBuffers, StringRef CompilationDir="", SmallVectorImpl< object::BuildIDRef > *BinaryIDs=nullptr)

LLVM_ABI Counter subtract(Counter LHS, Counter RHS, bool Simplify=true)

Return a counter that represents the expression that subtracts RHS from LHS.

Definition CoverageMapping.cpp:132

LLVM_ABI Counter add(Counter LHS, Counter RHS, bool Simplify=true)

Return a counter that represents the expression that adds LHS and RHS.

Definition CoverageMapping.cpp:127

LLVM_ABI Counter subst(Counter C, const SubstMap &Map)

Definition CoverageMapping.cpp:138

std::map< Counter, Counter > SubstMap

K to V map.

A Counter mapping context is used to connect the counters, expressions and the obtained counter value...

LLVM_ABI Expected< MCDCRecord > evaluateMCDCRegion(const CounterMappingRegion &Region, ArrayRef< const CounterMappingRegion * > Branches, bool IsVersion11)

Return an MCDC record that indicates executed test vectors and condition pairs.

Definition CoverageMapping.cpp:554

LLVM_ABI Expected< int64_t > evaluate(const Counter &C) const

Return the number of times that a region of code associated with this counter was executed.

Definition CoverageMapping.cpp:193

LLVM_ABI unsigned getMaxCounterID(const Counter &C) const

Definition CoverageMapping.cpp:562

LLVM_ABI void dump(const Counter &C, raw_ostream &OS) const

Definition CoverageMapping.cpp:163

Coverage information to be processed or displayed.

std::string message() const override

Return the error message as a string.

Definition CoverageMapping.cpp:1676

coveragemap_error get() const

const std::string & getMessage() const

static LLVM_ABI Expected< std::unique_ptr< CoverageMapping > > load(ArrayRef< std::unique_ptr< CoverageMappingReader > > CoverageReaders, std::optional< std::reference_wrapper< IndexedInstrProfReader > > &ProfileReader)

Load the coverage mapping using the given readers.

Definition CoverageMapping.cpp:992

LLVM_ABI std::vector< StringRef > getUniqueSourceFiles() const

Returns a lexicographically sorted, unique list of files that are covered.

Definition CoverageMapping.cpp:1399

LLVM_ABI CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion) const

Get the coverage for an expansion within a coverage set.

Definition CoverageMapping.cpp:1539

iterator_range< FunctionRecordIterator > getCoveredFunctions() const

Gets all of the functions covered by this profile.

LLVM_ABI CoverageData getCoverageForFunction(const FunctionRecord &Function) const

Get the coverage for a particular function.

Definition CoverageMapping.cpp:1507

LLVM_ABI std::vector< InstantiationGroup > getInstantiationGroups(StringRef Filename) const

Get the list of function instantiation groups in a particular file.

Definition CoverageMapping.cpp:1482

LLVM_ABI CoverageData getCoverageForFile(StringRef Filename) const

Get the coverage for a particular file.

Definition CoverageMapping.cpp:1446

Iterator over Functions, optionally filtered to a single file.

An instantiation group contains a FunctionRecord list, such that each record corresponds to a distinc...

LineCoverageIterator(const CoverageData &CD)

LLVM_ABI LineCoverageIterator & operator++()

Definition CoverageMapping.cpp:1607

Coverage statistics for a single line.

auto getIndex() const

Equivalent to buildTestVector's Index.

void set(int I, CondState Val)

Set the condition Val at position I.

Compute TestVector Indices "TVIdx" from the Conds graph.

static constexpr auto HardMaxTVs

Hard limit of test vectors.

LLVM_ABI TVIdxBuilder(const SmallVectorImpl< ConditionIDs > &NextIDs, int Offset=0)

Calculate and assign Indices.

Definition CoverageMapping.cpp:283

SmallVector< std::array< int, 2 > > Indices

Output: Index for TestVectors bitmap (These are not CondIDs)

int NumTestVectors

Output: The number of test vectors.

SmallVector< MCDCNode > SavedNodes

This is no longer needed after the assignment.

std::pair< iterator, bool > insert(const ValueT &V)

bool contains(const_arg_type_t< ValueT > V) const

Check if the set contains the given element.

BuildIDFetcher searches local cache directories for debug info.

virtual std::optional< std::string > fetch(BuildIDRef BuildID) const

Returns the path to the debug file with the given build ID.

This class implements an extremely fast bulk output stream that can only output to a stream.

A raw_ostream that writes to an std::string.

The virtual file system interface.

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

unsigned ID

LLVM IR allows to use arbitrary numbers as calling convention identifiers.

@ C

The default llvm calling convention, compatible with C.

@ Skipped

Validation was skipped, as it was not needed.

int16_t ConditionID

The ID for MCDCBranch.

std::array< ConditionID, 2 > ConditionIDs

LLVM_ABI const std::error_category & coveragemap_category()

Definition CoverageMapping.cpp:1680

std::pair< unsigned, unsigned > LineColPair

@ invalid_or_missing_arch_specifier

SmallVector< uint8_t, 10 > BuildID

A build ID in binary form.

ArrayRef< uint8_t > BuildIDRef

A reference to a BuildID in binary form.

This is an optimization pass for GlobalISel generic memory operations.

hash_code hash_value(const FixedPointSemantics &Val)

Error createFileError(const Twine &F, Error E)

Concatenate a source file path and/or name with an Error.

auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)

Get the size of a range.

auto enumerate(FirstRange &&First, RestRanges &&...Rest)

Given two or more input ranges, returns a new range whose values are tuples (A, B,...

LLVM_ABI StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName="")

Given a PGO function name, remove the filename prefix and return the original (static) function name.

Error handleErrors(Error E, HandlerTs &&... Hs)

Pass the ErrorInfo(s) contained in E to their respective handlers.

void append_range(Container &C, Range &&R)

Wrapper function to append range R to container C.

auto unique(Range &&R, Predicate P)

Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)

Create formatted StringError object.

auto map_range(ContainerTy &&C, FuncTy F)

@ no_such_file_or_directory

bool any_of(R &&range, UnaryPredicate P)

Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.

auto reverse(ContainerTy &&C)

void sort(IteratorTy Start, IteratorTy End)

LLVM_ABI raw_ostream & dbgs()

dbgs() - This returns a reference to a raw_ostream for debugging messages.

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

MutableArrayRef(T &OneElt) -> MutableArrayRef< T >

Error make_error(ArgTs &&... Args)

Make a Error instance representing failure using the given error info type.

std::string join(IteratorT Begin, IteratorT End, StringRef Separator)

Joins the strings in the range [Begin, End), adding Separator between the elements.

uint64_t alignTo(uint64_t Size, Align A)

Returns a multiple of A needed to store Size bytes.

ArrayRef(const T &OneElt) -> ArrayRef< T >

void toHex(ArrayRef< uint8_t > Input, bool LowerCase, SmallVectorImpl< char > &Output)

Convert buffer Input to its hexadecimal representation. The returned string is double the size of Inp...

auto find_if(R &&Range, UnaryPredicate P)

Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.

LLVM_ABI Error errorCodeToError(std::error_code EC)

Helper for converting an std::error_code to a Error.

void consumeError(Error Err)

Consume a Error without doing anything.

hash_code hash_combine_range(InputIteratorT first, InputIteratorT last)

Compute a hash_code for a sequence of values.

Associates a source range with an execution count.

A Counter expression is a value that represents an arithmetic operation with two counters.

A Counter mapping region associates a source range with a specific counter.

@ ExpansionRegion

An ExpansionRegion represents a file expansion region that associates a source range with the expansi...

@ MCDCDecisionRegion

A DecisionRegion represents a top-level boolean expression and is associated with a variable length b...

@ MCDCBranchRegion

A Branch Region can be extended to include IDs to facilitate MC/DC.

@ SkippedRegion

A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...

@ GapRegion

A GapRegion is like a CodeRegion, but its count is only set as the line execution count when its the ...

@ CodeRegion

A CodeRegion associates some code with a counter.

A Counter is an abstract value that describes how to compute the execution count for a region of code...

static Counter getZero()

Return the counter that represents the number zero.

static Counter getCounter(unsigned CounterId)

Return the counter that corresponds to a specific profile counter.

static Counter getExpression(unsigned ExpressionId)

Return the counter that corresponds to a specific addition counter expression.

Coverage mapping information for a single function.

ArrayRef< CounterExpression > Expressions

ArrayRef< CounterMappingRegion > MappingRegions

ArrayRef< StringRef > Filenames

The execution count information starting at a point in a file.

Coverage information for a macro expansion or included file.

Code coverage information for a single function.

llvm::SmallVector< std::pair< TestVector, CondState > > TestVectors

LLVM_ABI void findIndependencePairs()

Definition CoverageMapping.cpp:253

llvm::DenseMap< unsigned, unsigned > CondIDMap

llvm::DenseMap< unsigned, LineColPair > LineColPairMap

std::array< BitVector, 2 > BoolVector

llvm::DenseMap< unsigned, TVRowPair > TVPairMap

uint16_t NumConditions

Number of Conditions used for a Decision Region.