17 #include "llvm/ADT/SmallSet.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/ADT/Optional.h" 20 #include "llvm/ProfileData/Coverage/CoverageMapping.h" 21 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 22 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" 23 #include "llvm/ProfileData/InstrProfReader.h" 24 #include "llvm/Support/FileSystem.h" 25 #include "llvm/Support/Path.h" 27 using namespace clang;
28 using namespace CodeGen;
32 SkippedRanges.push_back(Range);
38 class SourceMappingRegion {
57 bool GapRegion =
false)
58 : Count(Count), LocStart(LocStart), LocEnd(LocEnd),
59 DeferRegion(DeferRegion), GapRegion(GapRegion) {}
61 const Counter &getCounter()
const {
return Count; }
63 void setCounter(Counter C) { Count = C; }
65 bool hasStartLoc()
const {
return LocStart.hasValue(); }
70 assert(LocStart &&
"Region has no start location");
74 bool hasEndLoc()
const {
return LocEnd.hasValue(); }
77 assert(Loc.
isValid() &&
"Setting an invalid end location");
82 assert(LocEnd &&
"Region has no end location");
86 bool isDeferred()
const {
return DeferRegion; }
88 void setDeferred(
bool Deferred) { DeferRegion = Deferred; }
90 bool isGap()
const {
return GapRegion; }
92 void setGap(
bool Gap) { GapRegion = Gap; }
96 struct SpellingRegion {
101 unsigned ColumnStart;
118 : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
122 bool isInSourceOrder()
const {
123 return (LineStart < LineEnd) ||
124 (LineStart == LineEnd && ColumnStart <= ColumnEnd);
130 class CoverageMappingBuilder {
138 llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
145 std::vector<SourceMappingRegion> SourceRegions;
152 typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
157 : CVM(CVM),
SM(SM), LangOpts(LangOpts) {}
197 Loc = getIncludeOrExpansionLoc(Loc);
217 return getPreciseTokenLocEnd(Loc);
226 FileIDMapping.clear();
228 llvm::SmallSet<FileID, 8> Visited;
230 for (
const auto &Region : SourceRegions) {
233 if (!Visited.insert(File).second)
242 Parent.
isValid(); Parent = getIncludeOrExpansionLoc(Parent))
244 FileLocs.push_back(std::make_pair(Loc, Depth));
246 llvm::stable_sort(FileLocs, llvm::less_second());
248 for (
const auto &FL : FileLocs) {
255 FileIDMapping[SM.
getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
264 auto Mapping = FileIDMapping.find(SM.
getFileID(Loc));
265 if (Mapping != FileIDMapping.end())
266 return Mapping->second.first;
272 void gatherSkippedRegions() {
276 FileLineRanges.resize(
277 FileIDMapping.size(),
279 for (
const auto &R : MappingRegions) {
280 FileLineRanges[R.FileID].first =
281 std::min(FileLineRanges[R.FileID].first, R.LineStart);
282 FileLineRanges[R.FileID].second =
283 std::max(FileLineRanges[R.FileID].second, R.LineEnd);
287 for (
const auto &I : SkippedRanges) {
288 auto LocStart = I.getBegin();
289 auto LocEnd = I.getEnd();
291 "region spans multiple files");
293 auto CovFileID = getCoverageFileID(LocStart);
296 SpellingRegion SR{
SM, LocStart, LocEnd};
297 auto Region = CounterMappingRegion::makeSkipped(
298 *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd);
301 if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
302 Region.LineEnd <= FileLineRanges[*CovFileID].second)
303 MappingRegions.push_back(Region);
309 void emitSourceRegions(
const SourceRegionFilter &
Filter) {
310 for (
const auto &Region : SourceRegions) {
311 assert(Region.hasEndLoc() &&
"incomplete region");
320 auto CovFileID = getCoverageFileID(LocStart);
327 "region spans multiple files");
333 if (Filter.count(std::make_pair(LocStart, LocEnd)))
337 SpellingRegion SR{
SM, LocStart, LocEnd};
338 assert(SR.isInSourceOrder() &&
"region start and end out of order");
340 if (Region.isGap()) {
341 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
342 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
343 SR.LineEnd, SR.ColumnEnd));
345 MappingRegions.push_back(CounterMappingRegion::makeRegion(
346 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
347 SR.LineEnd, SR.ColumnEnd));
353 SourceRegionFilter emitExpansionRegions() {
354 SourceRegionFilter
Filter;
355 for (
const auto &FM : FileIDMapping) {
361 auto ParentFileID = getCoverageFileID(ParentLoc);
364 auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
365 assert(ExpandedFileID &&
"expansion in uncovered file");
369 "region spans multiple files");
370 Filter.insert(std::make_pair(ParentLoc, LocEnd));
372 SpellingRegion SR{
SM, ParentLoc, LocEnd};
373 assert(SR.isInSourceOrder() &&
"region start and end out of order");
374 MappingRegions.push_back(CounterMappingRegion::makeExpansion(
375 *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
376 SR.LineEnd, SR.ColumnEnd));
384 struct EmptyCoverageMappingBuilder :
public CoverageMappingBuilder {
387 : CoverageMappingBuilder(CVM, SM, LangOpts) {}
389 void VisitDecl(
const Decl *D) {
400 while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
401 Start = getIncludeOrExpansionLoc(Start);
403 "Declaration start location not nested within a known region");
406 while (StartFileID != EndFileID) {
407 End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
409 "Declaration end location not nested within a known region");
413 SourceRegions.emplace_back(Counter(), Start, End);
417 void write(llvm::raw_ostream &OS) {
419 gatherFileIDs(FileIDMapping);
420 emitSourceRegions(SourceRegionFilter());
422 if (MappingRegions.empty())
425 CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
432 struct CounterCoverageMappingBuilder
433 :
public CoverageMappingBuilder,
436 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
439 std::vector<SourceMappingRegion> RegionStack;
445 CounterExpressionBuilder Builder;
457 Counter subtractCounters(Counter LHS, Counter RHS) {
458 return Builder.subtract(LHS, RHS);
462 Counter addCounters(Counter LHS, Counter RHS) {
463 return Builder.add(LHS, RHS);
466 Counter addCounters(Counter C1, Counter C2, Counter C3) {
467 return addCounters(addCounters(C1, C2), C3);
473 Counter getRegionCounter(
const Stmt *S) {
474 return Counter::getCounter(CounterMap[S]);
484 MostRecentLocation = *StartLoc;
485 completeDeferred(Count, MostRecentLocation);
487 RegionStack.emplace_back(Count, StartLoc, EndLoc);
489 return RegionStack.size() - 1;
494 size_t completeDeferred(Counter Count,
SourceLocation DeferredEndLoc) {
495 size_t Index = RegionStack.size();
500 SourceMappingRegion DR = DeferredRegion.getValue();
501 DeferredRegion = None;
506 if (isNestedIn(DeferredEndLoc, StartFile)) {
508 DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc);
509 }
while (StartFile !=
SM.
getFileID(DeferredEndLoc));
517 if (DR.getBeginLoc() == DeferredEndLoc)
522 if (!SpellingRegion(
SM, DR.getBeginLoc(), DeferredEndLoc).isInSourceOrder())
526 DR.setCounter(Count);
527 DR.setEndLoc(DeferredEndLoc);
528 handleFileExit(DeferredEndLoc);
529 RegionStack.push_back(DR);
535 void completeTopLevelDeferredRegion(Counter Count,
537 if (DeferredRegion || !LastTerminatedRegion)
540 if (LastTerminatedRegion->second != RegionStack.size())
547 SourceMappingRegion DR = RegionStack.back();
548 DR.setStartLoc(Start);
549 DR.setDeferred(
false);
551 completeDeferred(Count, DeferredEndLoc);
557 Loc = getIncludeOrExpansionLoc(Loc);
567 void popRegions(
size_t ParentIndex) {
568 assert(RegionStack.size() >= ParentIndex &&
"parent not in stack");
569 bool ParentOfDeferredRegion =
false;
570 while (RegionStack.size() > ParentIndex) {
571 SourceMappingRegion &Region = RegionStack.back();
572 if (Region.hasStartLoc()) {
576 : RegionStack[ParentIndex].getEndLoc();
577 size_t StartDepth = locationDepth(StartLoc);
578 size_t EndDepth = locationDepth(EndLoc);
580 bool UnnestStart = StartDepth >= EndDepth;
581 bool UnnestEnd = EndDepth >= StartDepth;
588 if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
589 SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
591 EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
593 llvm::report_fatal_error(
"File exit not handled before popRegions");
602 if (!isRegionAlreadyAdded(StartLoc, NestedLoc))
603 SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc);
605 StartLoc = getIncludeOrExpansionLoc(StartLoc);
607 llvm::report_fatal_error(
"File exit not handled before popRegions");
611 Region.setStartLoc(StartLoc);
612 Region.setEndLoc(EndLoc);
614 MostRecentLocation = EndLoc;
617 if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
618 EndLoc == getEndOfFileOrMacro(EndLoc))
619 MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
622 assert(SpellingRegion(
SM, Region).isInSourceOrder());
623 SourceRegions.push_back(Region);
625 if (ParentOfDeferredRegion) {
626 ParentOfDeferredRegion =
false;
630 if (!DeferredRegion.hasValue() &&
635 SourceMappingRegion(Counter::getZero(), EndLoc, None);
637 }
else if (Region.isDeferred()) {
638 assert(!ParentOfDeferredRegion &&
"Consecutive deferred regions");
639 ParentOfDeferredRegion =
true;
641 RegionStack.pop_back();
645 if (LastTerminatedRegion &&
646 RegionStack.size() < LastTerminatedRegion->second)
647 LastTerminatedRegion = None;
649 assert(!ParentOfDeferredRegion &&
"Deferred region with no parent");
653 SourceMappingRegion &getRegion() {
654 assert(!RegionStack.empty() &&
"statement has no region");
655 return RegionStack.back();
660 Counter propagateCounts(Counter TopCount,
const Stmt *S,
661 bool VisitChildren =
true) {
664 size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
667 Counter ExitCount = getRegion().getCounter();
673 MostRecentLocation = EndLoc;
681 return SourceRegions.rend() !=
682 std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
683 [&](
const SourceMappingRegion &Region) {
684 return Region.getBeginLoc() == StartLoc &&
685 Region.getEndLoc() == EndLoc;
693 MostRecentLocation = EndLoc;
699 if (getRegion().hasEndLoc() &&
700 MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
701 isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
703 MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
720 while (!isNestedIn(MostRecentLocation, ParentFile)) {
721 LCA = getIncludeOrExpansionLoc(LCA);
725 MostRecentLocation = NewLoc;
731 llvm::SmallSet<SourceLocation, 8> StartLocs;
733 for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
734 if (!I.hasStartLoc())
737 if (!isNestedIn(Loc, ParentFile)) {
738 ParentCounter = I.getCounter();
746 if (StartLocs.insert(Loc).second)
747 SourceRegions.emplace_back(I.getCounter(), Loc,
748 getEndOfFileOrMacro(Loc));
749 Loc = getIncludeOrExpansionLoc(Loc);
751 I.setStartLoc(getPreciseTokenLocEnd(Loc));
759 while (isNestedIn(Loc, ParentFile)) {
761 if (StartLocs.insert(FileStart).second) {
762 SourceRegions.emplace_back(*ParentCounter, FileStart,
763 getEndOfFileOrMacro(Loc));
764 assert(SpellingRegion(
SM, SourceRegions.back()).isInSourceOrder());
766 Loc = getIncludeOrExpansionLoc(Loc);
770 MostRecentLocation = NewLoc;
774 void extendRegion(
const Stmt *S) {
775 SourceMappingRegion &Region = getRegion();
778 handleFileExit(StartLoc);
779 if (!Region.hasStartLoc())
780 Region.setStartLoc(StartLoc);
782 completeDeferred(Region.getCounter(), StartLoc);
786 void terminateRegion(
const Stmt *S) {
788 SourceMappingRegion &Region = getRegion();
790 if (!Region.hasEndLoc())
791 Region.setEndLoc(EndLoc);
792 pushRegion(Counter::getZero());
793 auto &ZeroRegion = getRegion();
794 ZeroRegion.setDeferred(
true);
795 LastTerminatedRegion = {EndLoc, RegionStack.size()};
807 return {{AfterLoc, BeforeLoc}};
812 const Stmt *BeforeStmt) {
813 return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)),
814 getStart(BeforeStmt));
820 if (StartLoc == EndLoc)
822 assert(SpellingRegion(
SM, StartLoc, EndLoc).isInSourceOrder());
823 handleFileExit(StartLoc);
824 size_t Index = pushRegion(Count, StartLoc, EndLoc);
825 getRegion().setGap(
true);
826 handleFileExit(EndLoc);
831 struct BreakContinue {
833 Counter ContinueCount;
837 CounterCoverageMappingBuilder(
841 : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
842 DeferredRegion(None) {}
845 void write(llvm::raw_ostream &OS) {
847 gatherFileIDs(VirtualFileMapping);
848 SourceRegionFilter
Filter = emitExpansionRegions();
849 assert(!DeferredRegion &&
"Deferred region never completed");
850 emitSourceRegions(Filter);
851 gatherSkippedRegions();
853 if (MappingRegions.empty())
856 CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
861 void VisitStmt(
const Stmt *S) {
867 handleFileExit(getEnd(S));
870 void VisitDecl(
const Decl *D) {
871 assert(!DeferredRegion &&
"Deferred region never completed");
883 bool Defaulted =
false;
884 if (
auto *Method = dyn_cast<CXXMethodDecl>(D))
885 Defaulted = Method->isDefaulted();
887 propagateCounts(getRegionCounter(Body), Body,
889 assert(RegionStack.empty() &&
"Regions entered but never exited");
894 DeferredRegion = None;
911 void VisitGotoStmt(
const GotoStmt *S) { terminateRegion(S); }
913 void VisitLabelStmt(
const LabelStmt *S) {
914 Counter LabelCount = getRegionCounter(S);
916 completeTopLevelDeferredRegion(LabelCount, Start);
917 completeDeferred(LabelCount, Start);
919 handleFileExit(Start);
920 pushRegion(LabelCount, Start);
924 void VisitBreakStmt(
const BreakStmt *S) {
925 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
926 BreakContinueStack.back().BreakCount = addCounters(
927 BreakContinueStack.back().BreakCount, getRegion().getCounter());
934 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
935 BreakContinueStack.back().ContinueCount = addCounters(
936 BreakContinueStack.back().ContinueCount, getRegion().getCounter());
940 void VisitCallExpr(
const CallExpr *E) {
950 void VisitWhileStmt(
const WhileStmt *S) {
953 Counter ParentCount = getRegion().getCounter();
954 Counter BodyCount = getRegionCounter(S);
957 BreakContinueStack.push_back(BreakContinue());
959 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
960 BreakContinue BC = BreakContinueStack.pop_back_val();
964 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
965 propagateCounts(CondCount, S->
getCond());
966 adjustForOutOfOrderTraversal(getEnd(S));
971 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
974 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
975 if (OutCount != ParentCount)
976 pushRegion(OutCount);
979 void VisitDoStmt(
const DoStmt *S) {
982 Counter ParentCount = getRegion().getCounter();
983 Counter BodyCount = getRegionCounter(S);
985 BreakContinueStack.push_back(BreakContinue());
987 Counter BackedgeCount =
988 propagateCounts(addCounters(ParentCount, BodyCount), S->
getBody());
989 BreakContinue BC = BreakContinueStack.pop_back_val();
991 Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
992 propagateCounts(CondCount, S->
getCond());
995 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
996 if (OutCount != ParentCount)
997 pushRegion(OutCount);
1000 void VisitForStmt(
const ForStmt *S) {
1005 Counter ParentCount = getRegion().getCounter();
1006 Counter BodyCount = getRegionCounter(S);
1010 BreakContinueStack.emplace_back();
1013 BreakContinueStack.emplace_back();
1015 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1016 BreakContinue BodyBC = BreakContinueStack.pop_back_val();
1020 BreakContinue IncrementBC;
1022 propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
1023 IncrementBC = BreakContinueStack.pop_back_val();
1027 Counter CondCount = addCounters(
1028 addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
1029 IncrementBC.ContinueCount);
1031 propagateCounts(CondCount, Cond);
1032 adjustForOutOfOrderTraversal(getEnd(S));
1036 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1039 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1041 Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
1042 subtractCounters(CondCount, BodyCount));
1043 if (OutCount != ParentCount)
1044 pushRegion(OutCount);
1054 Counter ParentCount = getRegion().getCounter();
1055 Counter BodyCount = getRegionCounter(S);
1057 BreakContinueStack.push_back(BreakContinue());
1059 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1060 BreakContinue BC = BreakContinueStack.pop_back_val();
1063 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1066 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1069 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1071 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1072 if (OutCount != ParentCount)
1073 pushRegion(OutCount);
1080 Counter ParentCount = getRegion().getCounter();
1081 Counter BodyCount = getRegionCounter(S);
1083 BreakContinueStack.push_back(BreakContinue());
1085 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1086 BreakContinue BC = BreakContinueStack.pop_back_val();
1089 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1092 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1095 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1097 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1098 if (OutCount != ParentCount)
1099 pushRegion(OutCount);
1108 BreakContinueStack.push_back(BreakContinue());
1112 if (
const auto *CS = dyn_cast<CompoundStmt>(Body)) {
1113 if (!CS->body_empty()) {
1118 pushRegion(Counter::getZero(), getStart(CS->body_front()));
1119 for (
const auto *Child : CS->children())
1123 for (
size_t i = RegionStack.size(); i != Index; --i) {
1124 if (!RegionStack[i - 1].hasEndLoc())
1125 RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
1131 propagateCounts(Counter::getZero(), Body);
1132 BreakContinue BC = BreakContinueStack.pop_back_val();
1134 if (!BreakContinueStack.empty())
1135 BreakContinueStack.back().ContinueCount = addCounters(
1136 BreakContinueStack.back().ContinueCount, BC.ContinueCount);
1138 Counter ExitCount = getRegionCounter(S);
1140 pushRegion(ExitCount);
1144 MostRecentLocation = getStart(S);
1145 handleFileExit(ExitLoc);
1151 SourceMappingRegion &
Parent = getRegion();
1153 Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
1156 if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
1157 Parent.setCounter(Count);
1159 pushRegion(Count, getStart(S));
1161 if (
const auto *CS = dyn_cast<CaseStmt>(S)) {
1162 Visit(CS->getLHS());
1163 if (
const Expr *RHS = CS->getRHS())
1169 void VisitIfStmt(
const IfStmt *S) {
1178 Counter ParentCount = getRegion().getCounter();
1179 Counter ThenCount = getRegionCounter(S);
1183 propagateCounts(ParentCount, S->
getCond());
1188 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
1191 Counter OutCount = propagateCounts(ThenCount, S->
getThen());
1193 Counter ElseCount = subtractCounters(ParentCount, ThenCount);
1196 Gap = findGapAreaBetween(S->
getThen(), Else);
1198 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
1200 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1202 OutCount = addCounters(OutCount, ElseCount);
1204 if (OutCount != ParentCount)
1205 pushRegion(OutCount);
1213 Counter ParentCount = getRegion().getCounter();
1219 Counter ExitCount = getRegionCounter(S);
1220 pushRegion(ExitCount);
1230 Counter ParentCount = getRegion().getCounter();
1231 Counter TrueCount = getRegionCounter(E);
1235 if (!isa<BinaryConditionalOperator>(E)) {
1240 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
1247 propagateCounts(subtractCounters(ParentCount, TrueCount),
1252 extendRegion(E->
getLHS());
1253 propagateCounts(getRegion().getCounter(), E->
getLHS());
1254 handleFileExit(getEnd(E->
getLHS()));
1256 extendRegion(E->
getRHS());
1257 propagateCounts(getRegionCounter(E), E->
getRHS());
1261 extendRegion(E->
getLHS());
1262 propagateCounts(getRegion().getCounter(), E->
getLHS());
1263 handleFileExit(getEnd(E->
getLHS()));
1265 extendRegion(E->
getRHS());
1266 propagateCounts(getRegionCounter(E), E->
getRHS());
1276 return llvm::getInstrProfSectionName(
1283 static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
1286 OS << FunctionName <<
":\n";
1287 CounterMappingContext Ctx(Expressions);
1288 for (
const auto &R : Regions) {
1291 case CounterMappingRegion::CodeRegion:
1293 case CounterMappingRegion::ExpansionRegion:
1296 case CounterMappingRegion::SkippedRegion:
1299 case CounterMappingRegion::GapRegion:
1304 OS <<
"File " << R.FileID <<
", " << R.LineStart <<
":" << R.ColumnStart
1305 <<
" -> " << R.LineEnd <<
":" << R.ColumnEnd <<
" = ";
1306 Ctx.dump(R.Count, OS);
1307 if (R.Kind == CounterMappingRegion::ExpansionRegion)
1308 OS <<
" (Expanded file = " << R.ExpandedFileID <<
")";
1315 : CGM(CGM), SourceInfo(SourceInfo), FunctionRecordTy(nullptr) {
1321 llvm::sys::fs::current_path(CWD);
1324 std::string CoverageMappingModuleGen::normalizeFilename(StringRef
Filename) {
1326 llvm::sys::fs::make_absolute(CWD, Path);
1327 llvm::sys::path::remove_dots(Path,
true);
1328 return Path.str().str();
1332 llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1333 const std::string &CoverageMapping,
bool IsUsed) {
1335 if (!FunctionRecordTy) {
1336 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, 1338 #include "llvm/ProfileData/InstrProfData.inc" 1341 llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
1345 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, 1346 llvm::Constant *FunctionRecordVals[] = {
1347 #include "llvm/ProfileData/InstrProfData.inc" 1349 FunctionRecords.push_back(llvm::ConstantStruct::get(
1350 FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
1352 FunctionNames.push_back(
1353 llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
1354 CoverageMappings.push_back(CoverageMapping);
1362 std::vector<StringRef> Filenames;
1363 std::vector<CounterExpression> Expressions;
1364 std::vector<CounterMappingRegion> Regions;
1367 FilenameStrs.resize(FileEntries.size());
1368 FilenameRefs.resize(FileEntries.size());
1369 for (
const auto &Entry : FileEntries) {
1370 auto I = Entry.second;
1371 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1372 FilenameRefs[I] = FilenameStrs[I];
1374 RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
1375 Expressions, Regions);
1378 dump(llvm::outs(), NameValue, Expressions, Regions);
1383 if (FunctionRecords.empty())
1386 auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1391 FilenameStrs.resize(FileEntries.size());
1392 FilenameRefs.resize(FileEntries.size());
1393 for (
const auto &Entry : FileEntries) {
1394 auto I = Entry.second;
1395 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1396 FilenameRefs[I] = FilenameStrs[I];
1399 std::string FilenamesAndCoverageMappings;
1400 llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
1401 CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
1405 size_t CoverageMappingSize = 0;
1406 for (
auto &S : CoverageMappings) {
1407 CoverageMappingSize += S.size();
1412 CoverageMappings.clear();
1413 CoverageMappings.shrink_to_fit();
1415 size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
1418 if (
size_t Rem = OS.str().size() % 8) {
1419 CoverageMappingSize += 8 - Rem;
1420 OS.write_zeros(8 - Rem);
1422 auto *FilenamesAndMappingsVal =
1423 llvm::ConstantDataArray::getString(Ctx, OS.str(),
false);
1427 llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
1428 auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
1431 #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, 1432 #include "llvm/ProfileData/InstrProfData.inc" 1434 auto CovDataHeaderTy =
1435 llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
1436 llvm::Constant *CovDataHeaderVals[] = {
1437 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, 1438 #include "llvm/ProfileData/InstrProfData.inc" 1440 auto CovDataHeaderVal = llvm::ConstantStruct::get(
1441 CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
1444 llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
1445 FilenamesAndMappingsVal->getType()};
1446 auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1447 llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
1448 FilenamesAndMappingsVal};
1450 llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
1451 auto CovData =
new llvm::GlobalVariable(
1453 CovDataVal, llvm::getCoverageMappingVarName());
1455 CovData->setSection(getCoverageSection(CGM));
1456 CovData->setAlignment(llvm::Align(8));
1461 if (!FunctionNames.empty()) {
1462 auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
1463 FunctionNames.size());
1464 auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
1467 new llvm::GlobalVariable(CGM.
getModule(), NamesArrTy,
true,
1469 llvm::getCoverageUnusedNamesVarName());
1474 auto It = FileEntries.find(File);
1475 if (It != FileEntries.end())
1477 unsigned FileID = FileEntries.size();
1478 FileEntries.insert(std::make_pair(File,
FileID));
1483 llvm::raw_ostream &OS) {
1485 CounterCoverageMappingBuilder Walker(CVM, *CounterMap,
SM, LangOpts);
1486 Walker.VisitDecl(D);
1491 llvm::raw_ostream &OS) {
1492 EmptyCoverageMappingBuilder Walker(CVM,
SM, LangOpts);
1493 Walker.VisitDecl(D);
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
bool isWrittenInSameFile(SourceLocation Loc1, SourceLocation Loc2) const
Returns true if the spelling locations for both SourceLocations are part of the same file buffer...
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
A (possibly-)qualified type.
const CodeGenOptions & getCodeGenOpts() const
const Expr * getSubExpr() const
SourceLocation getLocForEndOfFile(FileID FID) const
Return the source location corresponding to the last byte of the specified file.
ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.
llvm::LLVMContext & getLLVMContext()
virtual Stmt * getBody() const
getBody - If this Decl represents a declaration for a body of code, such as a function or method defi...
Stmt - This represents one statement.
CXXCatchStmt * getHandler(unsigned i)
IfStmt - This represents an if/then/else.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
StringRef getBufferName(SourceLocation Loc, bool *Invalid=nullptr) const
Return the filename or buffer identifier of the buffer the location is in.
Decl - This represents one declaration (or definition), e.g.
Stmt * getHandlerBlock() const
bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const
Determines the order of 2 source locations in the translation unit.
Expr * getFalseExpr() const
Stores additional source code information like skipped ranges which is required by the coverage mappi...
const TargetInfo & getTargetInfo() const
A C++ throw-expression (C++ [except.throw]).
void emit()
Emit the coverage mapping data for a translation unit.
LabelStmt - Represents a label, which has a substatement.
SourceLocation getBegin() const
SourceLocation getBeginLoc() const LLVM_READONLY
void addFunctionMappingRecord(llvm::GlobalVariable *FunctionName, StringRef FunctionNameValue, uint64_t FunctionHash, const std::string &CoverageMapping, bool IsUsed=true)
Add a function's coverage mapping record to the collection of the function mapping records...
__DEVICE__ int max(int __a, int __b)
SourceLocation getQuestionLoc() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
ForStmt - This represents a 'for (init;cond;inc)' stmt.
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
SourceLocation getRParenLoc() const
A builtin binary operation expression such as "x + y" or "x <= y".
CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for statement, represented as 'for (ra...
unsigned getSpellingLineNumber(SourceLocation Loc, bool *Invalid=nullptr) const
SourceLocation getSpellingLoc(SourceLocation Loc) const
Given a SourceLocation object, return the spelling location referenced by the ID. ...
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
unsigned getFileIDSize(FileID FID) const
The size of the SLocEntry that FID represents.
bool isInFileID(SourceLocation Loc, FileID FID, unsigned *RelativeOffset=nullptr) const
Given a specific FileID, returns true if Loc is inside that FileID chunk and sets relative offset (of...
This represents one expression.
bool isInSystemHeader(SourceLocation Loc) const
Returns if a SourceLocation is in a system header.
static unsigned MeasureTokenLength(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts)
MeasureTokenLength - Relex the token at the specified location and return its length in bytes in the ...
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
Organizes the cross-function state that is used while generating code coverage mapping data...
CXXTryStmt - A C++ try block, including all handlers.
void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override
Hook called when a source range is skipped.
CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;...
Expr * getTrueExpr() const
ASTContext & getContext() const
SourceLocation getEndLoc() const LLVM_READONLY
unsigned getFileID(const FileEntry *File)
Return the coverage mapping translation unit file id for the given file.
DoStmt - This represents a 'do/while' stmt.
virtual bool hasBody() const
Returns true if this Decl represents a declaration for a body of code, such as a function or method d...
The l-value was considered opaque, so the alignment was determined from a type.
unsigned getFileOffset(SourceLocation SpellingLoc) const
Returns the offset from the start of the file that the specified SourceLocation represents.
std::pair< FileID, unsigned > getDecomposedSpellingLoc(SourceLocation Loc) const
Decompose the specified location into a raw FileID + Offset pair.
Encodes a location in the source.
unsigned getNumHandlers() const
ArrayRef< SourceRange > getSkippedRanges() const
Cached information about one file (either on disk or in the virtual file system). ...
CoverageSourceInfo & getSourceInfo() const
void addUsedGlobal(llvm::GlobalValue *GV)
Add a global to a list to be added to the llvm.used metadata.
unsigned getSpellingColumnNumber(SourceLocation Loc, bool *Invalid=nullptr) const
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
This class organizes the cross-function state that is used while generating LLVM code.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getIncludeLoc(FileID FID) const
Returns the include location if FID is a #include'd file otherwise it returns an invalid location...
FileID getMainFileID() const
Returns the FileID of the main source file.
std::string DebugCompilationDir
The string to embed in debug information as the current working directory.
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
llvm::Module & getModule() const
CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
SwitchStmt - This represents a 'switch' stmt.
FileID getFileID(SourceLocation SpellingLoc) const
Return the FileID for a SourceLocation.
SourceLocation getRParenLoc() const
bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc=nullptr) const
Tests whether the given source location represents a macro argument's expansion into the function-lik...
Represents Objective-C's collection statement.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Internal linkage, which indicates that the entity can be referred to from within the translation unit...
SourceLocation getRParenLoc() const
DeclStmt * getRangeStmt()
GotoStmt - This represents a direct goto.
void emitCounterMapping(const Decl *D, llvm::raw_ostream &OS)
Emit the coverage mapping data which maps the regions of code to counters that will be used to find t...
ContinueStmt - This represents a continue.
CXXCatchStmt - This represents a C++ catch block.
bool LE(InterpState &S, CodePtr OpPC)
WhileStmt - This represents a 'while' stmt.
CompoundStmt * getTryBlock()
__DEVICE__ int min(int __a, int __b)
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
BreakStmt - This represents a break.
DeclStmt * getLoopVarStmt()
A trivial tuple used to represent a source range.
void emitEmptyMapping(const Decl *D, llvm::raw_ostream &OS)
Emit the coverage mapping data for an unused function.
This class handles loading and caching of source files into memory.