18 #include "llvm/ADT/SmallSet.h" 19 #include "llvm/ADT/StringExtras.h" 20 #include "llvm/ADT/Optional.h" 21 #include "llvm/ProfileData/Coverage/CoverageMapping.h" 22 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h" 23 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h" 24 #include "llvm/ProfileData/InstrProfReader.h" 25 #include "llvm/Support/FileSystem.h" 26 #include "llvm/Support/Path.h" 28 using namespace clang;
29 using namespace CodeGen;
33 SkippedRanges.push_back(Range);
39 class SourceMappingRegion {
58 bool GapRegion =
false)
59 : Count(Count), LocStart(LocStart), LocEnd(LocEnd),
60 DeferRegion(DeferRegion), GapRegion(GapRegion) {}
62 const Counter &getCounter()
const {
return Count; }
64 void setCounter(Counter C) { Count = C; }
66 bool hasStartLoc()
const {
return LocStart.hasValue(); }
70 SourceLocation getStartLoc()
const LLVM_READONLY {
return getBeginLoc(); }
72 assert(LocStart &&
"Region has no start location");
76 bool hasEndLoc()
const {
return LocEnd.hasValue(); }
79 assert(Loc.
isValid() &&
"Setting an invalid end location");
84 assert(LocEnd &&
"Region has no end location");
88 bool isDeferred()
const {
return DeferRegion; }
90 void setDeferred(
bool Deferred) { DeferRegion = Deferred; }
92 bool isGap()
const {
return GapRegion; }
94 void setGap(
bool Gap) { GapRegion = Gap; }
98 struct SpellingRegion {
103 unsigned ColumnStart;
120 : SpellingRegion(SM, R.getStartLoc(), R.getEndLoc()) {}
124 bool isInSourceOrder()
const {
125 return (LineStart < LineEnd) ||
126 (LineStart == LineEnd && ColumnStart <= ColumnEnd);
132 class CoverageMappingBuilder {
140 llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
147 std::vector<SourceMappingRegion> SourceRegions;
154 typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
159 : CVM(CVM),
SM(SM), LangOpts(LangOpts) {}
199 Loc = getIncludeOrExpansionLoc(Loc);
219 return getPreciseTokenLocEnd(Loc);
228 FileIDMapping.clear();
230 llvm::SmallSet<FileID, 8> Visited;
232 for (
const auto &Region : SourceRegions) {
235 if (!Visited.insert(File).second)
244 Parent.
isValid(); Parent = getIncludeOrExpansionLoc(Parent))
246 FileLocs.push_back(std::make_pair(Loc, Depth));
248 std::stable_sort(FileLocs.begin(), FileLocs.end(), llvm::less_second());
250 for (
const auto &FL : FileLocs) {
257 FileIDMapping[SM.
getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
266 auto Mapping = FileIDMapping.find(SM.
getFileID(Loc));
267 if (Mapping != FileIDMapping.end())
268 return Mapping->second.first;
274 void gatherSkippedRegions() {
278 FileLineRanges.resize(
279 FileIDMapping.size(),
281 for (
const auto &R : MappingRegions) {
282 FileLineRanges[R.FileID].first =
283 std::min(FileLineRanges[R.FileID].first, R.LineStart);
284 FileLineRanges[R.FileID].second =
285 std::max(FileLineRanges[R.FileID].second, R.LineEnd);
289 for (
const auto &I : SkippedRanges) {
290 auto LocStart = I.getBegin();
291 auto LocEnd = I.getEnd();
293 "region spans multiple files");
295 auto CovFileID = getCoverageFileID(LocStart);
298 SpellingRegion SR{
SM, LocStart, LocEnd};
299 auto Region = CounterMappingRegion::makeSkipped(
300 *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd);
303 if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
304 Region.LineEnd <= FileLineRanges[*CovFileID].second)
305 MappingRegions.push_back(Region);
311 void emitSourceRegions(
const SourceRegionFilter &Filter) {
312 for (
const auto &Region : SourceRegions) {
313 assert(Region.hasEndLoc() &&
"incomplete region");
322 auto CovFileID = getCoverageFileID(LocStart);
329 "region spans multiple files");
335 if (Filter.count(std::make_pair(LocStart, LocEnd)))
339 SpellingRegion SR{
SM, LocStart, LocEnd};
340 assert(SR.isInSourceOrder() &&
"region start and end out of order");
342 if (Region.isGap()) {
343 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
344 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
345 SR.LineEnd, SR.ColumnEnd));
347 MappingRegions.push_back(CounterMappingRegion::makeRegion(
348 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
349 SR.LineEnd, SR.ColumnEnd));
355 SourceRegionFilter emitExpansionRegions() {
356 SourceRegionFilter Filter;
357 for (
const auto &FM : FileIDMapping) {
363 auto ParentFileID = getCoverageFileID(ParentLoc);
366 auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
367 assert(ExpandedFileID &&
"expansion in uncovered file");
371 "region spans multiple files");
372 Filter.insert(std::make_pair(ParentLoc, LocEnd));
374 SpellingRegion SR{
SM, ParentLoc, LocEnd};
375 assert(SR.isInSourceOrder() &&
"region start and end out of order");
376 MappingRegions.push_back(CounterMappingRegion::makeExpansion(
377 *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
378 SR.LineEnd, SR.ColumnEnd));
386 struct EmptyCoverageMappingBuilder :
public CoverageMappingBuilder {
389 : CoverageMappingBuilder(CVM, SM, LangOpts) {}
391 void VisitDecl(
const Decl *D) {
402 while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
403 Start = getIncludeOrExpansionLoc(Start);
405 "Declaration start location not nested within a known region");
408 while (StartFileID != EndFileID) {
409 End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
411 "Declaration end location not nested within a known region");
415 SourceRegions.emplace_back(Counter(), Start, End);
419 void write(llvm::raw_ostream &OS) {
421 gatherFileIDs(FileIDMapping);
422 emitSourceRegions(SourceRegionFilter());
424 if (MappingRegions.empty())
427 CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
434 struct CounterCoverageMappingBuilder
435 :
public CoverageMappingBuilder,
438 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
441 std::vector<SourceMappingRegion> RegionStack;
447 CounterExpressionBuilder Builder;
459 Counter subtractCounters(Counter LHS, Counter RHS) {
460 return Builder.subtract(LHS, RHS);
464 Counter addCounters(Counter LHS, Counter RHS) {
465 return Builder.add(LHS, RHS);
468 Counter addCounters(Counter C1, Counter C2, Counter C3) {
469 return addCounters(addCounters(C1, C2), C3);
475 Counter getRegionCounter(
const Stmt *S) {
476 return Counter::getCounter(CounterMap[S]);
486 MostRecentLocation = *StartLoc;
487 completeDeferred(Count, MostRecentLocation);
489 RegionStack.emplace_back(Count, StartLoc, EndLoc);
491 return RegionStack.size() - 1;
496 size_t completeDeferred(Counter Count,
SourceLocation DeferredEndLoc) {
497 size_t Index = RegionStack.size();
502 SourceMappingRegion DR = DeferredRegion.getValue();
503 DeferredRegion = None;
508 if (isNestedIn(DeferredEndLoc, StartFile)) {
510 DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc);
511 }
while (StartFile !=
SM.
getFileID(DeferredEndLoc));
519 if (DR.getStartLoc() == DeferredEndLoc)
524 if (!SpellingRegion(
SM, DR.getStartLoc(), DeferredEndLoc).isInSourceOrder())
528 DR.setCounter(Count);
529 DR.setEndLoc(DeferredEndLoc);
530 handleFileExit(DeferredEndLoc);
531 RegionStack.push_back(DR);
537 void completeTopLevelDeferredRegion(Counter Count,
539 if (DeferredRegion || !LastTerminatedRegion)
542 if (LastTerminatedRegion->second != RegionStack.size())
549 SourceMappingRegion DR = RegionStack.back();
550 DR.setStartLoc(Start);
551 DR.setDeferred(
false);
553 completeDeferred(Count, DeferredEndLoc);
560 void popRegions(
size_t ParentIndex) {
561 assert(RegionStack.size() >= ParentIndex &&
"parent not in stack");
562 bool ParentOfDeferredRegion =
false;
563 while (RegionStack.size() > ParentIndex) {
564 SourceMappingRegion &Region = RegionStack.back();
565 if (Region.hasStartLoc()) {
569 : RegionStack[ParentIndex].getEndLoc();
576 if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
577 SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
579 EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
581 llvm::report_fatal_error(
"File exit not handled before popRegions");
583 Region.setEndLoc(EndLoc);
585 MostRecentLocation = EndLoc;
588 if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
589 EndLoc == getEndOfFileOrMacro(EndLoc))
590 MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
593 assert(SpellingRegion(
SM, Region).isInSourceOrder());
594 SourceRegions.push_back(Region);
596 if (ParentOfDeferredRegion) {
597 ParentOfDeferredRegion =
false;
601 if (!DeferredRegion.hasValue() &&
606 SourceMappingRegion(Counter::getZero(), EndLoc, None);
608 }
else if (Region.isDeferred()) {
609 assert(!ParentOfDeferredRegion &&
"Consecutive deferred regions");
610 ParentOfDeferredRegion =
true;
612 RegionStack.pop_back();
616 if (LastTerminatedRegion &&
617 RegionStack.size() < LastTerminatedRegion->second)
618 LastTerminatedRegion = None;
620 assert(!ParentOfDeferredRegion &&
"Deferred region with no parent");
624 SourceMappingRegion &getRegion() {
625 assert(!RegionStack.empty() &&
"statement has no region");
626 return RegionStack.back();
630 Counter propagateCounts(Counter TopCount,
const Stmt *S) {
633 size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
635 Counter ExitCount = getRegion().getCounter();
641 MostRecentLocation = EndLoc;
649 return SourceRegions.rend() !=
650 std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
651 [&](
const SourceMappingRegion &Region) {
652 return Region.getStartLoc() == StartLoc &&
653 Region.getEndLoc() == EndLoc;
661 MostRecentLocation = EndLoc;
667 if (getRegion().hasEndLoc() &&
668 MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
669 isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
671 MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
688 while (!isNestedIn(MostRecentLocation, ParentFile)) {
689 LCA = getIncludeOrExpansionLoc(LCA);
693 MostRecentLocation = NewLoc;
699 llvm::SmallSet<SourceLocation, 8> StartLocs;
701 for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
702 if (!I.hasStartLoc())
705 if (!isNestedIn(Loc, ParentFile)) {
706 ParentCounter = I.getCounter();
714 if (StartLocs.insert(Loc).second)
715 SourceRegions.emplace_back(I.getCounter(), Loc,
716 getEndOfFileOrMacro(Loc));
717 Loc = getIncludeOrExpansionLoc(Loc);
719 I.setStartLoc(getPreciseTokenLocEnd(Loc));
727 while (isNestedIn(Loc, ParentFile)) {
729 if (StartLocs.insert(FileStart).second) {
730 SourceRegions.emplace_back(*ParentCounter, FileStart,
731 getEndOfFileOrMacro(Loc));
732 assert(SpellingRegion(
SM, SourceRegions.back()).isInSourceOrder());
734 Loc = getIncludeOrExpansionLoc(Loc);
738 MostRecentLocation = NewLoc;
742 void extendRegion(
const Stmt *S) {
743 SourceMappingRegion &Region = getRegion();
746 handleFileExit(StartLoc);
747 if (!Region.hasStartLoc())
748 Region.setStartLoc(StartLoc);
750 completeDeferred(Region.getCounter(), StartLoc);
754 void terminateRegion(
const Stmt *S) {
756 SourceMappingRegion &Region = getRegion();
758 if (!Region.hasEndLoc())
759 Region.setEndLoc(EndLoc);
760 pushRegion(Counter::getZero());
761 auto &ZeroRegion = getRegion();
762 ZeroRegion.setDeferred(
true);
763 LastTerminatedRegion = {EndLoc, RegionStack.size()};
775 return {{AfterLoc, BeforeLoc}};
780 const Stmt *BeforeStmt) {
781 return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)),
782 getStart(BeforeStmt));
788 if (StartLoc == EndLoc)
790 assert(SpellingRegion(
SM, StartLoc, EndLoc).isInSourceOrder());
791 handleFileExit(StartLoc);
792 size_t Index = pushRegion(Count, StartLoc, EndLoc);
793 getRegion().setGap(
true);
794 handleFileExit(EndLoc);
799 struct BreakContinue {
801 Counter ContinueCount;
805 CounterCoverageMappingBuilder(
809 : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
810 DeferredRegion(None) {}
813 void write(llvm::raw_ostream &OS) {
815 gatherFileIDs(VirtualFileMapping);
816 SourceRegionFilter Filter = emitExpansionRegions();
817 assert(!DeferredRegion &&
"Deferred region never completed");
818 emitSourceRegions(Filter);
819 gatherSkippedRegions();
821 if (MappingRegions.empty())
824 CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
829 void VisitStmt(
const Stmt *S) {
835 handleFileExit(getEnd(S));
838 void VisitDecl(
const Decl *D) {
839 assert(!DeferredRegion &&
"Deferred region never completed");
847 propagateCounts(getRegionCounter(Body), Body);
848 assert(RegionStack.empty() &&
"Regions entered but never exited");
853 DeferredRegion = None;
870 void VisitGotoStmt(
const GotoStmt *S) { terminateRegion(S); }
872 void VisitLabelStmt(
const LabelStmt *S) {
873 Counter LabelCount = getRegionCounter(S);
875 completeTopLevelDeferredRegion(LabelCount, Start);
876 completeDeferred(LabelCount, Start);
878 handleFileExit(Start);
879 pushRegion(LabelCount, Start);
883 void VisitBreakStmt(
const BreakStmt *S) {
884 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
885 BreakContinueStack.back().BreakCount = addCounters(
886 BreakContinueStack.back().BreakCount, getRegion().getCounter());
893 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
894 BreakContinueStack.back().ContinueCount = addCounters(
895 BreakContinueStack.back().ContinueCount, getRegion().getCounter());
899 void VisitCallExpr(
const CallExpr *E) {
909 void VisitWhileStmt(
const WhileStmt *S) {
912 Counter ParentCount = getRegion().getCounter();
913 Counter BodyCount = getRegionCounter(S);
916 BreakContinueStack.push_back(BreakContinue());
918 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
919 BreakContinue BC = BreakContinueStack.pop_back_val();
923 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
924 propagateCounts(CondCount, S->
getCond());
925 adjustForOutOfOrderTraversal(getEnd(S));
930 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
933 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
934 if (OutCount != ParentCount)
935 pushRegion(OutCount);
938 void VisitDoStmt(
const DoStmt *S) {
941 Counter ParentCount = getRegion().getCounter();
942 Counter BodyCount = getRegionCounter(S);
944 BreakContinueStack.push_back(BreakContinue());
946 Counter BackedgeCount =
947 propagateCounts(addCounters(ParentCount, BodyCount), S->
getBody());
948 BreakContinue BC = BreakContinueStack.pop_back_val();
950 Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
951 propagateCounts(CondCount, S->
getCond());
954 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
955 if (OutCount != ParentCount)
956 pushRegion(OutCount);
959 void VisitForStmt(
const ForStmt *S) {
964 Counter ParentCount = getRegion().getCounter();
965 Counter BodyCount = getRegionCounter(S);
969 BreakContinueStack.emplace_back();
972 BreakContinueStack.emplace_back();
974 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
975 BreakContinue BodyBC = BreakContinueStack.pop_back_val();
979 BreakContinue IncrementBC;
981 propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
982 IncrementBC = BreakContinueStack.pop_back_val();
986 Counter CondCount = addCounters(
987 addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
988 IncrementBC.ContinueCount);
990 propagateCounts(CondCount, Cond);
991 adjustForOutOfOrderTraversal(getEnd(S));
995 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
998 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1000 Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
1001 subtractCounters(CondCount, BodyCount));
1002 if (OutCount != ParentCount)
1003 pushRegion(OutCount);
1011 Counter ParentCount = getRegion().getCounter();
1012 Counter BodyCount = getRegionCounter(S);
1014 BreakContinueStack.push_back(BreakContinue());
1016 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1017 BreakContinue BC = BreakContinueStack.pop_back_val();
1020 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1023 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1026 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1028 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1029 if (OutCount != ParentCount)
1030 pushRegion(OutCount);
1037 Counter ParentCount = getRegion().getCounter();
1038 Counter BodyCount = getRegionCounter(S);
1040 BreakContinueStack.push_back(BreakContinue());
1042 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1043 BreakContinue BC = BreakContinueStack.pop_back_val();
1046 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1049 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1052 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1054 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1055 if (OutCount != ParentCount)
1056 pushRegion(OutCount);
1065 BreakContinueStack.push_back(BreakContinue());
1069 if (
const auto *CS = dyn_cast<CompoundStmt>(Body)) {
1070 if (!CS->body_empty()) {
1075 pushRegion(Counter::getZero(), getStart(CS->body_front()));
1076 for (
const auto *Child : CS->children())
1080 for (
size_t i = RegionStack.size(); i != Index; --i) {
1081 if (!RegionStack[i - 1].hasEndLoc())
1082 RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
1088 propagateCounts(Counter::getZero(), Body);
1089 BreakContinue BC = BreakContinueStack.pop_back_val();
1091 if (!BreakContinueStack.empty())
1092 BreakContinueStack.back().ContinueCount = addCounters(
1093 BreakContinueStack.back().ContinueCount, BC.ContinueCount);
1095 Counter ExitCount = getRegionCounter(S);
1097 pushRegion(ExitCount);
1101 MostRecentLocation = getStart(S);
1102 handleFileExit(ExitLoc);
1108 SourceMappingRegion &
Parent = getRegion();
1110 Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
1113 if (Parent.hasStartLoc() && Parent.getStartLoc() == getStart(S))
1114 Parent.setCounter(Count);
1116 pushRegion(Count, getStart(S));
1118 if (
const auto *CS = dyn_cast<CaseStmt>(S)) {
1119 Visit(CS->getLHS());
1120 if (
const Expr *RHS = CS->getRHS())
1126 void VisitIfStmt(
const IfStmt *S) {
1135 Counter ParentCount = getRegion().getCounter();
1136 Counter ThenCount = getRegionCounter(S);
1140 propagateCounts(ParentCount, S->
getCond());
1145 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
1148 Counter OutCount = propagateCounts(ThenCount, S->
getThen());
1150 Counter ElseCount = subtractCounters(ParentCount, ThenCount);
1153 Gap = findGapAreaBetween(S->
getThen(), Else);
1155 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
1157 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1159 OutCount = addCounters(OutCount, ElseCount);
1161 if (OutCount != ParentCount)
1162 pushRegion(OutCount);
1170 Counter ParentCount = getRegion().getCounter();
1176 Counter ExitCount = getRegionCounter(S);
1177 pushRegion(ExitCount);
1187 Counter ParentCount = getRegion().getCounter();
1188 Counter TrueCount = getRegionCounter(E);
1192 if (!isa<BinaryConditionalOperator>(E)) {
1197 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
1204 propagateCounts(subtractCounters(ParentCount, TrueCount),
1209 extendRegion(E->
getLHS());
1210 propagateCounts(getRegion().getCounter(), E->
getLHS());
1211 handleFileExit(getEnd(E->
getLHS()));
1213 extendRegion(E->
getRHS());
1214 propagateCounts(getRegionCounter(E), E->
getRHS());
1218 extendRegion(E->
getLHS());
1219 propagateCounts(getRegion().getCounter(), E->
getLHS());
1220 handleFileExit(getEnd(E->
getLHS()));
1222 extendRegion(E->
getRHS());
1223 propagateCounts(getRegionCounter(E), E->
getRHS());
1233 return llvm::getInstrProfSectionName(
1238 std::string normalizeFilename(StringRef
Filename) {
1240 llvm::sys::fs::make_absolute(Path);
1241 llvm::sys::path::remove_dots(Path,
true);
1242 return Path.str().str();
1247 static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
1250 OS << FunctionName <<
":\n";
1251 CounterMappingContext Ctx(Expressions);
1252 for (
const auto &R : Regions) {
1255 case CounterMappingRegion::CodeRegion:
1257 case CounterMappingRegion::ExpansionRegion:
1260 case CounterMappingRegion::SkippedRegion:
1263 case CounterMappingRegion::GapRegion:
1268 OS <<
"File " << R.FileID <<
", " << R.LineStart <<
":" << R.ColumnStart
1269 <<
" -> " << R.LineEnd <<
":" << R.ColumnEnd <<
" = ";
1270 Ctx.dump(R.Count, OS);
1271 if (R.Kind == CounterMappingRegion::ExpansionRegion)
1272 OS <<
" (Expanded file = " << R.ExpandedFileID <<
")";
1278 llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1279 const std::string &CoverageMapping,
bool IsUsed) {
1280 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1281 if (!FunctionRecordTy) {
1282 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, 1284 #include "llvm/ProfileData/InstrProfData.inc" 1287 llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
1291 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, 1292 llvm::Constant *FunctionRecordVals[] = {
1293 #include "llvm/ProfileData/InstrProfData.inc" 1295 FunctionRecords.push_back(llvm::ConstantStruct::get(
1296 FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
1298 FunctionNames.push_back(
1299 llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
1300 CoverageMappings.push_back(CoverageMapping);
1302 if (CGM.getCodeGenOpts().DumpCoverageMapping) {
1308 std::vector<StringRef> Filenames;
1309 std::vector<CounterExpression> Expressions;
1310 std::vector<CounterMappingRegion> Regions;
1313 FilenameStrs.resize(FileEntries.size());
1314 FilenameRefs.resize(FileEntries.size());
1315 for (
const auto &Entry : FileEntries) {
1316 auto I = Entry.second;
1317 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1318 FilenameRefs[I] = FilenameStrs[I];
1320 RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
1321 Expressions, Regions);
1324 dump(llvm::outs(), NameValue, Expressions, Regions);
1329 if (FunctionRecords.empty())
1331 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1332 auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1337 FilenameStrs.resize(FileEntries.size());
1338 FilenameRefs.resize(FileEntries.size());
1339 for (
const auto &Entry : FileEntries) {
1340 auto I = Entry.second;
1341 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1342 FilenameRefs[I] = FilenameStrs[I];
1345 std::string FilenamesAndCoverageMappings;
1346 llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
1347 CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
1348 std::string RawCoverageMappings =
1349 llvm::join(CoverageMappings.begin(), CoverageMappings.end(),
"");
1350 OS << RawCoverageMappings;
1351 size_t CoverageMappingSize = RawCoverageMappings.size();
1352 size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
1355 if (
size_t Rem = OS.str().size() % 8) {
1356 CoverageMappingSize += 8 - Rem;
1357 OS.write_zeros(8 - Rem);
1359 auto *FilenamesAndMappingsVal =
1360 llvm::ConstantDataArray::getString(Ctx, OS.str(),
false);
1364 llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
1365 auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
1368 #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, 1369 #include "llvm/ProfileData/InstrProfData.inc" 1371 auto CovDataHeaderTy =
1372 llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
1373 llvm::Constant *CovDataHeaderVals[] = {
1374 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, 1375 #include "llvm/ProfileData/InstrProfData.inc" 1377 auto CovDataHeaderVal = llvm::ConstantStruct::get(
1378 CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
1381 llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
1382 FilenamesAndMappingsVal->getType()};
1383 auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1384 llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
1385 FilenamesAndMappingsVal};
1387 llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
1388 auto CovData =
new llvm::GlobalVariable(
1390 CovDataVal, llvm::getCoverageMappingVarName());
1392 CovData->setSection(getCoverageSection(CGM));
1393 CovData->setAlignment(8);
1396 CGM.addUsedGlobal(CovData);
1398 if (!FunctionNames.empty()) {
1399 auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
1400 FunctionNames.size());
1401 auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
1404 new llvm::GlobalVariable(CGM.getModule(), NamesArrTy,
true,
1406 llvm::getCoverageUnusedNamesVarName());
1411 auto It = FileEntries.find(File);
1412 if (It != FileEntries.end())
1414 unsigned FileID = FileEntries.size();
1415 FileEntries.insert(std::make_pair(File,
FileID));
1420 llvm::raw_ostream &OS) {
1422 CounterCoverageMappingBuilder Walker(CVM, *CounterMap,
SM, LangOpts);
1423 Walker.VisitDecl(D);
1428 llvm::raw_ostream &OS) {
1429 EmptyCoverageMappingBuilder Walker(CVM,
SM, LangOpts);
1430 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...
const Stmt * getElse() const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
A (possibly-)qualified type.
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.
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
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
const Expr * getRetValue() const
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...
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...
Expr - 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...
const Stmt * getThen() const
const Expr * getCallee() const
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
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
SourceLocation getLocStart() const LLVM_READONLY
ArrayRef< SourceRange > getSkippedRanges() const
Cached information about one file (either on disk or in the virtual file system). ...
CoverageSourceInfo & getSourceInfo() const
SourceLocation getLocEnd() const LLVM_READONLY
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.
FunctionType::ExtInfo getFunctionExtInfo(const Type &t)
const Stmt * getBody() const
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.
WhileStmt - This represents a 'while' stmt.
CompoundStmt * getTryBlock()
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
__DEVICE__ int max(int __a, int __b)
BreakStmt - This represents a break.
__DEVICE__ int min(int __a, int __b)
DeclStmt * getLoopVarStmt()
const Expr * getCond() const
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.
const Expr * getCond() const
This class handles loading and caching of source files into memory.