comparison clang/lib/CodeGen/CoverageMappingGen.cpp @ 236:c4bab56944e8 llvm-original

LLVM 16
author kono
date Wed, 09 Nov 2022 17:45:10 +0900
parents 79ff65ed7e25
children 1f2b6ac9f198
comparison
equal deleted inserted replaced
232:70dce7da266c 236:c4bab56944e8
58 }); 58 });
59 } 59 }
60 return CoverageInfo; 60 return CoverageInfo;
61 } 61 }
62 62
63 void CoverageSourceInfo::AddSkippedRange(SourceRange Range) { 63 void CoverageSourceInfo::AddSkippedRange(SourceRange Range,
64 SkippedRange::Kind RangeKind) {
64 if (EmptyLineCommentCoverage && !SkippedRanges.empty() && 65 if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
65 PrevTokLoc == SkippedRanges.back().PrevTokLoc && 66 PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
66 SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(), 67 SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
67 Range.getBegin())) 68 Range.getBegin()))
68 SkippedRanges.back().Range.setEnd(Range.getEnd()); 69 SkippedRanges.back().Range.setEnd(Range.getEnd());
69 else 70 else
70 SkippedRanges.push_back({Range, PrevTokLoc}); 71 SkippedRanges.push_back({Range, RangeKind, PrevTokLoc});
71 } 72 }
72 73
73 void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) { 74 void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
74 AddSkippedRange(Range); 75 AddSkippedRange(Range, SkippedRange::PPIfElse);
75 } 76 }
76 77
77 void CoverageSourceInfo::HandleEmptyline(SourceRange Range) { 78 void CoverageSourceInfo::HandleEmptyline(SourceRange Range) {
78 AddSkippedRange(Range); 79 AddSkippedRange(Range, SkippedRange::EmptyLine);
79 } 80 }
80 81
81 bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) { 82 bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) {
82 AddSkippedRange(Range); 83 AddSkippedRange(Range, SkippedRange::Comment);
83 return false; 84 return false;
84 } 85 }
85 86
86 void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) { 87 void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) {
87 if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid()) 88 if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid())
127 return *FalseCount; 128 return *FalseCount;
128 } 129 }
129 130
130 void setCounter(Counter C) { Count = C; } 131 void setCounter(Counter C) { Count = C; }
131 132
132 bool hasStartLoc() const { return LocStart.hasValue(); } 133 bool hasStartLoc() const { return LocStart.has_value(); }
133 134
134 void setStartLoc(SourceLocation Loc) { LocStart = Loc; } 135 void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
135 136
136 SourceLocation getBeginLoc() const { 137 SourceLocation getBeginLoc() const {
137 assert(LocStart && "Region has no start location"); 138 assert(LocStart && "Region has no start location");
138 return *LocStart; 139 return *LocStart;
139 } 140 }
140 141
141 bool hasEndLoc() const { return LocEnd.hasValue(); } 142 bool hasEndLoc() const { return LocEnd.has_value(); }
142 143
143 void setEndLoc(SourceLocation Loc) { 144 void setEndLoc(SourceLocation Loc) {
144 assert(Loc.isValid() && "Setting an invalid end location"); 145 assert(Loc.isValid() && "Setting an invalid end location");
145 LocEnd = Loc; 146 LocEnd = Loc;
146 } 147 }
152 153
153 bool isGap() const { return GapRegion; } 154 bool isGap() const { return GapRegion; }
154 155
155 void setGap(bool Gap) { GapRegion = Gap; } 156 void setGap(bool Gap) { GapRegion = Gap; }
156 157
157 bool isBranch() const { return FalseCount.hasValue(); } 158 bool isBranch() const { return FalseCount.has_value(); }
158 }; 159 };
159 160
160 /// Spelling locations for the start and end of a source region. 161 /// Spelling locations for the start and end of a source region.
161 struct SpellingRegion { 162 struct SpellingRegion {
162 /// The line where the region starts. 163 /// The line where the region starts.
333 } 334 }
334 335
335 /// This shrinks the skipped range if it spans a line that contains a 336 /// This shrinks the skipped range if it spans a line that contains a
336 /// non-comment token. If shrinking the skipped range would make it empty, 337 /// non-comment token. If shrinking the skipped range would make it empty,
337 /// this returns None. 338 /// this returns None.
339 /// Note this function can potentially be expensive because
340 /// getSpellingLineNumber uses getLineNumber, which is expensive.
338 Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM, 341 Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
339 SourceLocation LocStart, 342 SourceLocation LocStart,
340 SourceLocation LocEnd, 343 SourceLocation LocEnd,
341 SourceLocation PrevTokLoc, 344 SourceLocation PrevTokLoc,
342 SourceLocation NextTokLoc) { 345 SourceLocation NextTokLoc) {
380 "region spans multiple files"); 383 "region spans multiple files");
381 384
382 auto CovFileID = getCoverageFileID(LocStart); 385 auto CovFileID = getCoverageFileID(LocStart);
383 if (!CovFileID) 386 if (!CovFileID)
384 continue; 387 continue;
385 Optional<SpellingRegion> SR = 388 Optional<SpellingRegion> SR;
386 adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, I.NextTokLoc); 389 if (I.isComment())
387 if (!SR.hasValue()) 390 SR = adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc,
391 I.NextTokLoc);
392 else if (I.isPPIfElse() || I.isEmptyLine())
393 SR = {SM, LocStart, LocEnd};
394
395 if (!SR)
388 continue; 396 continue;
389 auto Region = CounterMappingRegion::makeSkipped( 397 auto Region = CounterMappingRegion::makeSkipped(
390 *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd, 398 *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd,
391 SR->ColumnEnd); 399 SR->ColumnEnd);
392 // Make sure that we only collect the regions that are inside 400 // Make sure that we only collect the regions that are inside
548 556
549 /// Gap region counter after terminate statement. 557 /// Gap region counter after terminate statement.
550 Counter GapRegionCounter; 558 Counter GapRegionCounter;
551 559
552 /// Return a counter for the subtraction of \c RHS from \c LHS 560 /// Return a counter for the subtraction of \c RHS from \c LHS
553 Counter subtractCounters(Counter LHS, Counter RHS) { 561 Counter subtractCounters(Counter LHS, Counter RHS, bool Simplify = true) {
554 return Builder.subtract(LHS, RHS); 562 return Builder.subtract(LHS, RHS, Simplify);
555 } 563 }
556 564
557 /// Return a counter for the sum of \c LHS and \c RHS. 565 /// Return a counter for the sum of \c LHS and \c RHS.
558 Counter addCounters(Counter LHS, Counter RHS) { 566 Counter addCounters(Counter LHS, Counter RHS, bool Simplify = true) {
559 return Builder.add(LHS, RHS); 567 return Builder.add(LHS, RHS, Simplify);
560 } 568 }
561 569
562 Counter addCounters(Counter C1, Counter C2, Counter C3) { 570 Counter addCounters(Counter C1, Counter C2, Counter C3,
563 return addCounters(addCounters(C1, C2), C3); 571 bool Simplify = true) {
572 return addCounters(addCounters(C1, C2, Simplify), C3, Simplify);
564 } 573 }
565 574
566 /// Return the region counter for the given statement. 575 /// Return the region counter for the given statement.
567 /// 576 ///
568 /// This should only be called on statements that have a dedicated counter. 577 /// This should only be called on statements that have a dedicated counter.
576 /// used with popRegions to exit a "scope", ending the region that was pushed. 585 /// used with popRegions to exit a "scope", ending the region that was pushed.
577 size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None, 586 size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
578 Optional<SourceLocation> EndLoc = None, 587 Optional<SourceLocation> EndLoc = None,
579 Optional<Counter> FalseCount = None) { 588 Optional<Counter> FalseCount = None) {
580 589
581 if (StartLoc && !FalseCount.hasValue()) { 590 if (StartLoc && !FalseCount) {
582 MostRecentLocation = *StartLoc; 591 MostRecentLocation = *StartLoc;
583 } 592 }
584 593
585 RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc); 594 RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc);
586 595
749 758
750 /// Check whether a region with bounds \c StartLoc and \c EndLoc 759 /// Check whether a region with bounds \c StartLoc and \c EndLoc
751 /// is already added to \c SourceRegions. 760 /// is already added to \c SourceRegions.
752 bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc, 761 bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
753 bool isBranch = false) { 762 bool isBranch = false) {
754 return SourceRegions.rend() != 763 return llvm::any_of(
755 std::find_if(SourceRegions.rbegin(), SourceRegions.rend(), 764 llvm::reverse(SourceRegions), [&](const SourceMappingRegion &Region) {
756 [&](const SourceMappingRegion &Region) { 765 return Region.getBeginLoc() == StartLoc &&
757 return Region.getBeginLoc() == StartLoc && 766 Region.getEndLoc() == EndLoc && Region.isBranch() == isBranch;
758 Region.getEndLoc() == EndLoc && 767 });
759 Region.isBranch() == isBranch;
760 });
761 } 768 }
762 769
763 /// Adjust the most recently visited location to \c EndLoc. 770 /// Adjust the most recently visited location to \c EndLoc.
764 /// 771 ///
765 /// This should be used after visiting any statements in non-source order. 772 /// This should be used after visiting any statements in non-source order.
969 for (const Stmt *Child : S->children()) 976 for (const Stmt *Child : S->children())
970 if (Child) { 977 if (Child) {
971 // If last statement contains terminate statements, add a gap area 978 // If last statement contains terminate statements, add a gap area
972 // between the two statements. Skipping attributed statements, because 979 // between the two statements. Skipping attributed statements, because
973 // they don't have valid start location. 980 // they don't have valid start location.
974 if (LastStmt && HasTerminateStmt && !dyn_cast<AttributedStmt>(Child)) { 981 if (LastStmt && HasTerminateStmt && !isa<AttributedStmt>(Child)) {
975 auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child)); 982 auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
976 if (Gap) 983 if (Gap)
977 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), 984 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
978 GapRegionCounter); 985 GapRegionCounter);
979 SaveTerminateStmt = true; 986 SaveTerminateStmt = true;
1317 Counter CaseCountSum; 1324 Counter CaseCountSum;
1318 bool HasDefaultCase = false; 1325 bool HasDefaultCase = false;
1319 const SwitchCase *Case = S->getSwitchCaseList(); 1326 const SwitchCase *Case = S->getSwitchCaseList();
1320 for (; Case; Case = Case->getNextSwitchCase()) { 1327 for (; Case; Case = Case->getNextSwitchCase()) {
1321 HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case); 1328 HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1322 CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case)); 1329 CaseCountSum =
1330 addCounters(CaseCountSum, getRegionCounter(Case), /*Simplify=*/false);
1323 createSwitchCaseRegion( 1331 createSwitchCaseRegion(
1324 Case, getRegionCounter(Case), 1332 Case, getRegionCounter(Case),
1325 subtractCounters(ParentCount, getRegionCounter(Case))); 1333 subtractCounters(ParentCount, getRegionCounter(Case)));
1326 } 1334 }
1335 // Simplify is skipped while building the counters above: it can get really
1336 // slow on top of switches with thousands of cases. Instead, trigger
1337 // simplification by adding zero to the last counter.
1338 CaseCountSum = addCounters(CaseCountSum, Counter::getZero());
1327 1339
1328 // If no explicit default case exists, create a branch region to represent 1340 // If no explicit default case exists, create a branch region to represent
1329 // the hidden branch, which will be added later by the CodeGen. This region 1341 // the hidden branch, which will be added later by the CodeGen. This region
1330 // will be associated with the switch statement's condition. 1342 // will be associated with the switch statement's condition.
1331 if (!HasDefaultCase) { 1343 if (!HasDefaultCase) {
1363 if (S->getInit()) 1375 if (S->getInit())
1364 Visit(S->getInit()); 1376 Visit(S->getInit());
1365 1377
1366 // Extend into the condition before we propagate through it below - this is 1378 // Extend into the condition before we propagate through it below - this is
1367 // needed to handle macros that generate the "if" but not the condition. 1379 // needed to handle macros that generate the "if" but not the condition.
1368 extendRegion(S->getCond()); 1380 if (!S->isConsteval())
1381 extendRegion(S->getCond());
1369 1382
1370 Counter ParentCount = getRegion().getCounter(); 1383 Counter ParentCount = getRegion().getCounter();
1371 Counter ThenCount = getRegionCounter(S); 1384 Counter ThenCount = getRegionCounter(S);
1372 1385
1373 // Emitting a counter for the condition makes it easier to interpret the 1386 if (!S->isConsteval()) {
1374 // counter for the body when looking at the coverage. 1387 // Emitting a counter for the condition makes it easier to interpret the
1375 propagateCounts(ParentCount, S->getCond()); 1388 // counter for the body when looking at the coverage.
1376 1389 propagateCounts(ParentCount, S->getCond());
1377 // The 'then' count applies to the area immediately after the condition. 1390
1378 auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen())); 1391 // The 'then' count applies to the area immediately after the condition.
1379 if (Gap) 1392 Optional<SourceRange> Gap =
1380 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount); 1393 findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
1394 if (Gap)
1395 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
1396 }
1381 1397
1382 extendRegion(S->getThen()); 1398 extendRegion(S->getThen());
1383 Counter OutCount = propagateCounts(ThenCount, S->getThen()); 1399 Counter OutCount = propagateCounts(ThenCount, S->getThen());
1384 1400
1385 Counter ElseCount = subtractCounters(ParentCount, ThenCount); 1401 Counter ElseCount = subtractCounters(ParentCount, ThenCount);
1386 if (const Stmt *Else = S->getElse()) { 1402 if (const Stmt *Else = S->getElse()) {
1387 bool ThenHasTerminateStmt = HasTerminateStmt; 1403 bool ThenHasTerminateStmt = HasTerminateStmt;
1388 HasTerminateStmt = false; 1404 HasTerminateStmt = false;
1389
1390 // The 'else' count applies to the area immediately after the 'then'. 1405 // The 'else' count applies to the area immediately after the 'then'.
1391 Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else)); 1406 Optional<SourceRange> Gap =
1407 findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
1392 if (Gap) 1408 if (Gap)
1393 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount); 1409 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
1394 extendRegion(Else); 1410 extendRegion(Else);
1395 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else)); 1411 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1396 1412
1402 if (OutCount != ParentCount) { 1418 if (OutCount != ParentCount) {
1403 pushRegion(OutCount); 1419 pushRegion(OutCount);
1404 GapRegionCounter = OutCount; 1420 GapRegionCounter = OutCount;
1405 } 1421 }
1406 1422
1407 // Create Branch Region around condition. 1423 if (!S->isConsteval()) {
1408 createBranchRegion(S->getCond(), ThenCount, 1424 // Create Branch Region around condition.
1409 subtractCounters(ParentCount, ThenCount)); 1425 createBranchRegion(S->getCond(), ThenCount,
1426 subtractCounters(ParentCount, ThenCount));
1427 }
1410 } 1428 }
1411 1429
1412 void VisitCXXTryStmt(const CXXTryStmt *S) { 1430 void VisitCXXTryStmt(const CXXTryStmt *S) {
1413 extendRegion(S); 1431 extendRegion(S);
1414 // Handle macros that generate the "try" but not the rest. 1432 // Handle macros that generate the "try" but not the rest.