Mercurial > hg > CbC > CbC_llvm
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. |