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(); }
71 assert(LocStart &&
"Region has no start location");
75 bool hasEndLoc()
const {
return LocEnd.hasValue(); }
80 assert(LocEnd &&
"Region has no end location");
84 bool isDeferred()
const {
return DeferRegion; }
86 void setDeferred(
bool Deferred) { DeferRegion = Deferred; }
88 bool isGap()
const {
return GapRegion; }
90 void setGap(
bool Gap) { GapRegion = Gap; }
94 struct SpellingRegion {
116 : SpellingRegion(SM, R.getStartLoc(), R.getEndLoc()) {}
120 bool isInSourceOrder()
const {
121 return (LineStart < LineEnd) ||
122 (LineStart == LineEnd && ColumnStart <= ColumnEnd);
128 class CoverageMappingBuilder {
136 llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
143 std::vector<SourceMappingRegion> SourceRegions;
150 typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
155 : CVM(CVM),
SM(SM), LangOpts(LangOpts) {}
195 Loc = getIncludeOrExpansionLoc(Loc);
215 return getPreciseTokenLocEnd(Loc);
224 FileIDMapping.clear();
226 llvm::SmallSet<FileID, 8> Visited;
228 for (
const auto &Region : SourceRegions) {
231 if (!Visited.insert(File).second)
240 Parent.
isValid(); Parent = getIncludeOrExpansionLoc(Parent))
242 FileLocs.push_back(std::make_pair(Loc, Depth));
244 std::stable_sort(FileLocs.begin(), FileLocs.end(), llvm::less_second());
246 for (
const auto &FL : FileLocs) {
253 FileIDMapping[SM.
getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
262 auto Mapping = FileIDMapping.find(SM.
getFileID(Loc));
263 if (Mapping != FileIDMapping.end())
264 return Mapping->second.first;
270 void gatherSkippedRegions() {
274 FileLineRanges.resize(
275 FileIDMapping.size(),
277 for (
const auto &R : MappingRegions) {
278 FileLineRanges[R.FileID].first =
279 std::min(FileLineRanges[R.FileID].first, R.LineStart);
280 FileLineRanges[R.FileID].second =
281 std::max(FileLineRanges[R.FileID].second, R.LineEnd);
285 for (
const auto &I : SkippedRanges) {
286 auto LocStart = I.getBegin();
287 auto LocEnd = I.getEnd();
289 "region spans multiple files");
291 auto CovFileID = getCoverageFileID(LocStart);
294 SpellingRegion SR{
SM, LocStart, LocEnd};
295 auto Region = CounterMappingRegion::makeSkipped(
296 *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd);
299 if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
300 Region.LineEnd <= FileLineRanges[*CovFileID].second)
301 MappingRegions.push_back(Region);
307 void emitSourceRegions(
const SourceRegionFilter &Filter) {
308 for (
const auto &Region : SourceRegions) {
309 assert(Region.hasEndLoc() &&
"incomplete region");
318 auto CovFileID = getCoverageFileID(LocStart);
325 "region spans multiple files");
331 if (Filter.count(std::make_pair(LocStart, LocEnd)))
335 SpellingRegion SR{
SM, LocStart, LocEnd};
336 assert(SR.isInSourceOrder() &&
"region start and end out of order");
338 if (Region.isGap()) {
339 MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
340 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
341 SR.LineEnd, SR.ColumnEnd));
343 MappingRegions.push_back(CounterMappingRegion::makeRegion(
344 Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
345 SR.LineEnd, SR.ColumnEnd));
351 SourceRegionFilter emitExpansionRegions() {
352 SourceRegionFilter Filter;
353 for (
const auto &FM : FileIDMapping) {
359 auto ParentFileID = getCoverageFileID(ParentLoc);
362 auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
363 assert(ExpandedFileID &&
"expansion in uncovered file");
367 "region spans multiple files");
368 Filter.insert(std::make_pair(ParentLoc, LocEnd));
370 SpellingRegion SR{
SM, ParentLoc, LocEnd};
371 assert(SR.isInSourceOrder() &&
"region start and end out of order");
372 MappingRegions.push_back(CounterMappingRegion::makeExpansion(
373 *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
374 SR.LineEnd, SR.ColumnEnd));
382 struct EmptyCoverageMappingBuilder :
public CoverageMappingBuilder {
385 : CoverageMappingBuilder(CVM, SM, LangOpts) {}
387 void VisitDecl(
const Decl *D) {
398 while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
399 Start = getIncludeOrExpansionLoc(Start);
401 "Declaration start location not nested within a known region");
404 while (StartFileID != EndFileID) {
405 End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
407 "Declaration end location not nested within a known region");
411 SourceRegions.emplace_back(Counter(), Start, End);
415 void write(llvm::raw_ostream &OS) {
417 gatherFileIDs(FileIDMapping);
418 emitSourceRegions(SourceRegionFilter());
420 if (MappingRegions.empty())
423 CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
430 struct CounterCoverageMappingBuilder
431 :
public CoverageMappingBuilder,
434 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
437 std::vector<SourceMappingRegion> RegionStack;
443 CounterExpressionBuilder Builder;
455 Counter subtractCounters(Counter LHS, Counter RHS) {
456 return Builder.subtract(LHS, RHS);
460 Counter addCounters(Counter LHS, Counter RHS) {
461 return Builder.add(LHS, RHS);
464 Counter addCounters(Counter C1, Counter C2, Counter C3) {
465 return addCounters(addCounters(C1, C2), C3);
471 Counter getRegionCounter(
const Stmt *S) {
472 return Counter::getCounter(CounterMap[S]);
482 MostRecentLocation = *StartLoc;
483 completeDeferred(Count, MostRecentLocation);
485 RegionStack.emplace_back(Count, StartLoc, EndLoc);
487 return RegionStack.size() - 1;
492 size_t completeDeferred(Counter Count,
SourceLocation DeferredEndLoc) {
493 size_t Index = RegionStack.size();
498 SourceMappingRegion DR = DeferredRegion.getValue();
499 DeferredRegion = None;
504 if (isNestedIn(DeferredEndLoc, StartFile)) {
506 DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc);
507 }
while (StartFile !=
SM.
getFileID(DeferredEndLoc));
515 if (DR.getStartLoc() == DeferredEndLoc)
520 if (!SpellingRegion(
SM, DR.getStartLoc(), DeferredEndLoc).isInSourceOrder())
524 DR.setCounter(Count);
525 DR.setEndLoc(DeferredEndLoc);
526 handleFileExit(DeferredEndLoc);
527 RegionStack.push_back(DR);
533 void completeTopLevelDeferredRegion(Counter Count,
535 if (DeferredRegion || !LastTerminatedRegion)
538 if (LastTerminatedRegion->second != RegionStack.size())
545 SourceMappingRegion DR = RegionStack.back();
546 DR.setStartLoc(Start);
547 DR.setDeferred(
false);
549 completeDeferred(Count, DeferredEndLoc);
556 void popRegions(
size_t ParentIndex) {
557 assert(RegionStack.size() >= ParentIndex &&
"parent not in stack");
558 bool ParentOfDeferredRegion =
false;
559 while (RegionStack.size() > ParentIndex) {
560 SourceMappingRegion &Region = RegionStack.back();
561 if (Region.hasStartLoc()) {
565 : RegionStack[ParentIndex].getEndLoc();
572 if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
573 SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
575 EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
577 llvm::report_fatal_error(
"File exit not handled before popRegions");
579 Region.setEndLoc(EndLoc);
581 MostRecentLocation = EndLoc;
584 if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
585 EndLoc == getEndOfFileOrMacro(EndLoc))
586 MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
589 assert(SpellingRegion(
SM, Region).isInSourceOrder());
590 SourceRegions.push_back(Region);
592 if (ParentOfDeferredRegion) {
593 ParentOfDeferredRegion =
false;
597 if (!DeferredRegion.hasValue() &&
602 SourceMappingRegion(Counter::getZero(), EndLoc, None);
604 }
else if (Region.isDeferred()) {
605 assert(!ParentOfDeferredRegion &&
"Consecutive deferred regions");
606 ParentOfDeferredRegion =
true;
608 RegionStack.pop_back();
612 if (LastTerminatedRegion &&
613 RegionStack.size() < LastTerminatedRegion->second)
614 LastTerminatedRegion = None;
616 assert(!ParentOfDeferredRegion &&
"Deferred region with no parent");
620 SourceMappingRegion &getRegion() {
621 assert(!RegionStack.empty() &&
"statement has no region");
622 return RegionStack.back();
626 Counter propagateCounts(Counter TopCount,
const Stmt *S) {
629 size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
631 Counter ExitCount = getRegion().getCounter();
637 MostRecentLocation = EndLoc;
645 return SourceRegions.rend() !=
646 std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
647 [&](
const SourceMappingRegion &Region) {
648 return Region.getStartLoc() == StartLoc &&
649 Region.getEndLoc() == EndLoc;
657 MostRecentLocation = EndLoc;
663 if (getRegion().hasEndLoc() &&
664 MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
665 isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
667 MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
684 while (!isNestedIn(MostRecentLocation, ParentFile)) {
685 LCA = getIncludeOrExpansionLoc(LCA);
689 MostRecentLocation = NewLoc;
695 llvm::SmallSet<SourceLocation, 8> StartLocs;
697 for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
698 if (!I.hasStartLoc())
701 if (!isNestedIn(Loc, ParentFile)) {
702 ParentCounter = I.getCounter();
710 if (StartLocs.insert(Loc).second)
711 SourceRegions.emplace_back(I.getCounter(), Loc,
712 getEndOfFileOrMacro(Loc));
713 Loc = getIncludeOrExpansionLoc(Loc);
715 I.setStartLoc(getPreciseTokenLocEnd(Loc));
723 while (isNestedIn(Loc, ParentFile)) {
725 if (StartLocs.insert(FileStart).second) {
726 SourceRegions.emplace_back(*ParentCounter, FileStart,
727 getEndOfFileOrMacro(Loc));
728 assert(SpellingRegion(
SM, SourceRegions.back()).isInSourceOrder());
730 Loc = getIncludeOrExpansionLoc(Loc);
734 MostRecentLocation = NewLoc;
738 void extendRegion(
const Stmt *S) {
739 SourceMappingRegion &Region = getRegion();
742 handleFileExit(StartLoc);
743 if (!Region.hasStartLoc())
744 Region.setStartLoc(StartLoc);
746 completeDeferred(Region.getCounter(), StartLoc);
750 void terminateRegion(
const Stmt *S) {
752 SourceMappingRegion &Region = getRegion();
754 if (!Region.hasEndLoc())
755 Region.setEndLoc(EndLoc);
756 pushRegion(Counter::getZero());
757 auto &ZeroRegion = getRegion();
758 ZeroRegion.setDeferred(
true);
759 LastTerminatedRegion = {EndLoc, RegionStack.size()};
771 return {{AfterLoc, BeforeLoc}};
776 const Stmt *BeforeStmt) {
777 return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)),
778 getStart(BeforeStmt));
784 if (StartLoc == EndLoc)
786 assert(SpellingRegion(
SM, StartLoc, EndLoc).isInSourceOrder());
787 handleFileExit(StartLoc);
788 size_t Index = pushRegion(Count, StartLoc, EndLoc);
789 getRegion().setGap(
true);
790 handleFileExit(EndLoc);
795 struct BreakContinue {
797 Counter ContinueCount;
801 CounterCoverageMappingBuilder(
805 : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
806 DeferredRegion(None) {}
809 void write(llvm::raw_ostream &OS) {
811 gatherFileIDs(VirtualFileMapping);
812 SourceRegionFilter Filter = emitExpansionRegions();
813 assert(!DeferredRegion &&
"Deferred region never completed");
814 emitSourceRegions(Filter);
815 gatherSkippedRegions();
817 if (MappingRegions.empty())
820 CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
825 void VisitStmt(
const Stmt *S) {
831 handleFileExit(getEnd(S));
836 static bool discardFinalDeferredRegionInDecl(
Stmt *Body) {
837 if (
auto *CS = dyn_cast<CompoundStmt>(Body)) {
838 Stmt *LastStmt = CS->body_back();
839 if (
auto *IfElse = dyn_cast<IfStmt>(LastStmt)) {
840 if (
auto *Else = dyn_cast_or_null<CompoundStmt>(IfElse->getElse()))
841 LastStmt = Else->body_back();
843 LastStmt = IfElse->getElse();
845 return dyn_cast_or_null<ReturnStmt>(LastStmt);
850 void VisitDecl(
const Decl *D) {
851 assert(!DeferredRegion &&
"Deferred region never completed");
859 Counter ExitCount = propagateCounts(getRegionCounter(Body), Body);
860 assert(RegionStack.empty() &&
"Regions entered but never exited");
862 if (DeferredRegion) {
865 if (discardFinalDeferredRegionInDecl(Body))
866 DeferredRegion = None;
868 popRegions(completeDeferred(ExitCount, getEnd(Body)));
886 void VisitGotoStmt(
const GotoStmt *S) { terminateRegion(S); }
888 void VisitLabelStmt(
const LabelStmt *S) {
889 Counter LabelCount = getRegionCounter(S);
891 completeTopLevelDeferredRegion(LabelCount, Start);
893 handleFileExit(Start);
894 pushRegion(LabelCount, Start);
898 void VisitBreakStmt(
const BreakStmt *S) {
899 assert(!BreakContinueStack.empty() &&
"break not in a loop or switch!");
900 BreakContinueStack.back().BreakCount = addCounters(
901 BreakContinueStack.back().BreakCount, getRegion().getCounter());
908 assert(!BreakContinueStack.empty() &&
"continue stmt not in a loop!");
909 BreakContinueStack.back().ContinueCount = addCounters(
910 BreakContinueStack.back().ContinueCount, getRegion().getCounter());
914 void VisitCallExpr(
const CallExpr *E) {
924 void VisitWhileStmt(
const WhileStmt *S) {
927 Counter ParentCount = getRegion().getCounter();
928 Counter BodyCount = getRegionCounter(S);
931 BreakContinueStack.push_back(BreakContinue());
933 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
934 BreakContinue BC = BreakContinueStack.pop_back_val();
938 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
939 propagateCounts(CondCount, S->
getCond());
940 adjustForOutOfOrderTraversal(getEnd(S));
945 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
948 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
949 if (OutCount != ParentCount)
950 pushRegion(OutCount);
953 void VisitDoStmt(
const DoStmt *S) {
956 Counter ParentCount = getRegion().getCounter();
957 Counter BodyCount = getRegionCounter(S);
959 BreakContinueStack.push_back(BreakContinue());
961 Counter BackedgeCount =
962 propagateCounts(addCounters(ParentCount, BodyCount), S->
getBody());
963 BreakContinue BC = BreakContinueStack.pop_back_val();
965 Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
966 propagateCounts(CondCount, S->
getCond());
969 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
970 if (OutCount != ParentCount)
971 pushRegion(OutCount);
974 void VisitForStmt(
const ForStmt *S) {
979 Counter ParentCount = getRegion().getCounter();
980 Counter BodyCount = getRegionCounter(S);
983 BreakContinueStack.push_back(BreakContinue());
985 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
986 BreakContinue BC = BreakContinueStack.pop_back_val();
991 propagateCounts(addCounters(BackedgeCount, BC.ContinueCount), Inc);
995 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
997 propagateCounts(CondCount, Cond);
998 adjustForOutOfOrderTraversal(getEnd(S));
1002 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1005 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1008 addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1009 if (OutCount != ParentCount)
1010 pushRegion(OutCount);
1018 Counter ParentCount = getRegion().getCounter();
1019 Counter BodyCount = getRegionCounter(S);
1021 BreakContinueStack.push_back(BreakContinue());
1023 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1024 BreakContinue BC = BreakContinueStack.pop_back_val();
1027 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1030 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1033 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1035 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1036 if (OutCount != ParentCount)
1037 pushRegion(OutCount);
1044 Counter ParentCount = getRegion().getCounter();
1045 Counter BodyCount = getRegionCounter(S);
1047 BreakContinueStack.push_back(BreakContinue());
1049 Counter BackedgeCount = propagateCounts(BodyCount, S->
getBody());
1050 BreakContinue BC = BreakContinueStack.pop_back_val();
1053 auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->
getRParenLoc()),
1056 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
1059 addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
1061 addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1062 if (OutCount != ParentCount)
1063 pushRegion(OutCount);
1072 BreakContinueStack.push_back(BreakContinue());
1076 if (
const auto *CS = dyn_cast<CompoundStmt>(Body)) {
1077 if (!CS->body_empty()) {
1082 pushRegion(Counter::getZero(), getStart(CS->body_front()));
1083 for (
const auto *Child : CS->children())
1087 for (
size_t i = RegionStack.size(); i != Index; --i) {
1088 if (!RegionStack[i - 1].hasEndLoc())
1089 RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
1095 propagateCounts(Counter::getZero(), Body);
1096 BreakContinue BC = BreakContinueStack.pop_back_val();
1098 if (!BreakContinueStack.empty())
1099 BreakContinueStack.back().ContinueCount = addCounters(
1100 BreakContinueStack.back().ContinueCount, BC.ContinueCount);
1102 Counter ExitCount = getRegionCounter(S);
1104 pushRegion(ExitCount);
1108 MostRecentLocation = getStart(S);
1109 handleFileExit(ExitLoc);
1115 SourceMappingRegion &
Parent = getRegion();
1117 Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
1120 if (Parent.hasStartLoc() && Parent.getStartLoc() == getStart(S))
1121 Parent.setCounter(Count);
1123 pushRegion(Count, getStart(S));
1125 if (
const auto *CS = dyn_cast<CaseStmt>(S)) {
1126 Visit(CS->getLHS());
1127 if (
const Expr *RHS = CS->getRHS())
1133 void VisitIfStmt(
const IfStmt *S) {
1142 Counter ParentCount = getRegion().getCounter();
1143 Counter ThenCount = getRegionCounter(S);
1147 propagateCounts(ParentCount, S->
getCond());
1152 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
1155 Counter OutCount = propagateCounts(ThenCount, S->
getThen());
1157 Counter ElseCount = subtractCounters(ParentCount, ThenCount);
1160 Gap = findGapAreaBetween(S->
getThen(), Else);
1162 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
1164 OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1166 OutCount = addCounters(OutCount, ElseCount);
1168 if (OutCount != ParentCount)
1169 pushRegion(OutCount);
1177 Counter ParentCount = getRegion().getCounter();
1183 Counter ExitCount = getRegionCounter(S);
1184 pushRegion(ExitCount);
1194 Counter ParentCount = getRegion().getCounter();
1195 Counter TrueCount = getRegionCounter(E);
1199 if (!isa<BinaryConditionalOperator>(E)) {
1204 fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
1211 propagateCounts(subtractCounters(ParentCount, TrueCount),
1216 extendRegion(E->
getLHS());
1217 propagateCounts(getRegion().getCounter(), E->
getLHS());
1218 handleFileExit(getEnd(E->
getLHS()));
1220 extendRegion(E->
getRHS());
1221 propagateCounts(getRegionCounter(E), E->
getRHS());
1225 extendRegion(E->
getLHS());
1226 propagateCounts(getRegion().getCounter(), E->
getLHS());
1227 handleFileExit(getEnd(E->
getLHS()));
1229 extendRegion(E->
getRHS());
1230 propagateCounts(getRegionCounter(E), E->
getRHS());
1240 return llvm::getInstrProfSectionName(
1245 std::string normalizeFilename(StringRef
Filename) {
1247 llvm::sys::fs::make_absolute(Path);
1248 llvm::sys::path::remove_dots(Path,
true);
1249 return Path.str().str();
1254 static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
1257 OS << FunctionName <<
":\n";
1258 CounterMappingContext Ctx(Expressions);
1259 for (
const auto &R : Regions) {
1262 case CounterMappingRegion::CodeRegion:
1264 case CounterMappingRegion::ExpansionRegion:
1267 case CounterMappingRegion::SkippedRegion:
1270 case CounterMappingRegion::GapRegion:
1275 OS <<
"File " << R.FileID <<
", " << R.LineStart <<
":" << R.ColumnStart
1276 <<
" -> " << R.LineEnd <<
":" << R.ColumnEnd <<
" = ";
1277 Ctx.dump(R.Count, OS);
1278 if (R.Kind == CounterMappingRegion::ExpansionRegion)
1279 OS <<
" (Expanded file = " << R.ExpandedFileID <<
")";
1285 llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1286 const std::string &CoverageMapping,
bool IsUsed) {
1287 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1288 if (!FunctionRecordTy) {
1289 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType, 1291 #include "llvm/ProfileData/InstrProfData.inc" 1294 llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
1298 #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init, 1299 llvm::Constant *FunctionRecordVals[] = {
1300 #include "llvm/ProfileData/InstrProfData.inc" 1302 FunctionRecords.push_back(llvm::ConstantStruct::get(
1303 FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
1305 FunctionNames.push_back(
1306 llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
1307 CoverageMappings.push_back(CoverageMapping);
1309 if (CGM.getCodeGenOpts().DumpCoverageMapping) {
1315 std::vector<StringRef> Filenames;
1316 std::vector<CounterExpression> Expressions;
1317 std::vector<CounterMappingRegion> Regions;
1320 FilenameStrs.resize(FileEntries.size());
1321 FilenameRefs.resize(FileEntries.size());
1322 for (
const auto &Entry : FileEntries) {
1323 auto I = Entry.second;
1324 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1325 FilenameRefs[I] = FilenameStrs[I];
1327 RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
1328 Expressions, Regions);
1331 dump(llvm::outs(), NameValue, Expressions, Regions);
1336 if (FunctionRecords.empty())
1338 llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1339 auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
1344 FilenameStrs.resize(FileEntries.size());
1345 FilenameRefs.resize(FileEntries.size());
1346 for (
const auto &Entry : FileEntries) {
1347 auto I = Entry.second;
1348 FilenameStrs[I] = normalizeFilename(Entry.first->getName());
1349 FilenameRefs[I] = FilenameStrs[I];
1352 std::string FilenamesAndCoverageMappings;
1353 llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
1354 CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
1355 std::string RawCoverageMappings =
1356 llvm::join(CoverageMappings.begin(), CoverageMappings.end(),
"");
1357 OS << RawCoverageMappings;
1358 size_t CoverageMappingSize = RawCoverageMappings.size();
1359 size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
1362 if (
size_t Rem = OS.str().size() % 8) {
1363 CoverageMappingSize += 8 - Rem;
1364 for (
size_t I = 0, S = 8 - Rem; I < S; ++I)
1367 auto *FilenamesAndMappingsVal =
1368 llvm::ConstantDataArray::getString(Ctx, OS.str(),
false);
1372 llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
1373 auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
1376 #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType, 1377 #include "llvm/ProfileData/InstrProfData.inc" 1379 auto CovDataHeaderTy =
1380 llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
1381 llvm::Constant *CovDataHeaderVals[] = {
1382 #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init, 1383 #include "llvm/ProfileData/InstrProfData.inc" 1385 auto CovDataHeaderVal = llvm::ConstantStruct::get(
1386 CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
1389 llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
1390 FilenamesAndMappingsVal->getType()};
1391 auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1392 llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
1393 FilenamesAndMappingsVal};
1395 llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
1396 auto CovData =
new llvm::GlobalVariable(
1398 CovDataVal, llvm::getCoverageMappingVarName());
1400 CovData->setSection(getCoverageSection(CGM));
1401 CovData->setAlignment(8);
1404 CGM.addUsedGlobal(CovData);
1406 if (!FunctionNames.empty()) {
1407 auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
1408 FunctionNames.size());
1409 auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
1412 new llvm::GlobalVariable(CGM.getModule(), NamesArrTy,
true,
1414 llvm::getCoverageUnusedNamesVarName());
1419 auto It = FileEntries.find(File);
1420 if (It != FileEntries.end())
1422 unsigned FileID = FileEntries.size();
1423 FileEntries.insert(std::make_pair(File,
FileID));
1428 llvm::raw_ostream &OS) {
1430 CounterCoverageMappingBuilder Walker(CVM, *CounterMap,
SM, LangOpts);
1431 Walker.VisitDecl(D);
1436 llvm::raw_ostream &OS) {
1437 EmptyCoverageMappingBuilder Walker(CVM,
SM, LangOpts);
1438 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.
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.
SourceLocation getLocEnd() const LLVM_READONLY
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.
char __ovld __cnfn min(char x, char y)
Returns y if y < x, otherwise it returns x.
void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override
Hook called when a source range is skipped.
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.
std::pair< SourceLocation, SourceLocation > getImmediateExpansionRange(SourceLocation Loc) const
Return the start/end of the expansion information for an expansion location.
unsigned getNumHandlers() const
ArrayRef< SourceRange > getSkippedRanges() const
Cached information about one file (either on disk or in the virtual file system). ...
CoverageSourceInfo & getSourceInfo() const
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...
char __ovld __cnfn max(char x, char y)
Returns y if x < y, otherwise it returns x.
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]).
BreakStmt - This represents a break.
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
SourceLocation getLocStart() const LLVM_READONLY
This class handles loading and caching of source files into memory.