139d628a0SDimitry Andric //===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
239d628a0SDimitry Andric //
339d628a0SDimitry Andric // The LLVM Compiler Infrastructure
439d628a0SDimitry Andric //
539d628a0SDimitry Andric // This file is distributed under the University of Illinois Open Source
639d628a0SDimitry Andric // License. See LICENSE.TXT for details.
739d628a0SDimitry Andric //
839d628a0SDimitry Andric //===----------------------------------------------------------------------===//
939d628a0SDimitry Andric //
1039d628a0SDimitry Andric // Instrumentation-based code coverage mapping generator
1139d628a0SDimitry Andric //
1239d628a0SDimitry Andric //===----------------------------------------------------------------------===//
1339d628a0SDimitry Andric
1439d628a0SDimitry Andric #include "CoverageMappingGen.h"
1539d628a0SDimitry Andric #include "CodeGenFunction.h"
1639d628a0SDimitry Andric #include "clang/AST/StmtVisitor.h"
1739d628a0SDimitry Andric #include "clang/Lex/Lexer.h"
18e7145dcbSDimitry Andric #include "llvm/ADT/SmallSet.h"
19e7145dcbSDimitry Andric #include "llvm/ADT/StringExtras.h"
2033956c43SDimitry Andric #include "llvm/ADT/Optional.h"
21e7145dcbSDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h"
22e7145dcbSDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
23e7145dcbSDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
2439d628a0SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
2539d628a0SDimitry Andric #include "llvm/Support/FileSystem.h"
2644290647SDimitry Andric #include "llvm/Support/Path.h"
2739d628a0SDimitry Andric
2839d628a0SDimitry Andric using namespace clang;
2939d628a0SDimitry Andric using namespace CodeGen;
3039d628a0SDimitry Andric using namespace llvm::coverage;
3139d628a0SDimitry Andric
SourceRangeSkipped(SourceRange Range,SourceLocation)329a199699SDimitry Andric void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
3339d628a0SDimitry Andric SkippedRanges.push_back(Range);
3439d628a0SDimitry Andric }
3539d628a0SDimitry Andric
3639d628a0SDimitry Andric namespace {
3739d628a0SDimitry Andric
384ba319b5SDimitry Andric /// A region of source code that can be mapped to a counter.
3939d628a0SDimitry Andric class SourceMappingRegion {
4039d628a0SDimitry Andric Counter Count;
4139d628a0SDimitry Andric
424ba319b5SDimitry Andric /// The region's starting location.
4333956c43SDimitry Andric Optional<SourceLocation> LocStart;
4439d628a0SDimitry Andric
454ba319b5SDimitry Andric /// The region's ending location.
4633956c43SDimitry Andric Optional<SourceLocation> LocEnd;
4739d628a0SDimitry Andric
489a199699SDimitry Andric /// Whether this region should be emitted after its parent is emitted.
499a199699SDimitry Andric bool DeferRegion;
509a199699SDimitry Andric
519a199699SDimitry Andric /// Whether this region is a gap region. The count from a gap region is set
529a199699SDimitry Andric /// as the line execution count if there are no other regions on the line.
539a199699SDimitry Andric bool GapRegion;
549a199699SDimitry Andric
5539d628a0SDimitry Andric public:
SourceMappingRegion(Counter Count,Optional<SourceLocation> LocStart,Optional<SourceLocation> LocEnd,bool DeferRegion=false,bool GapRegion=false)5633956c43SDimitry Andric SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
579a199699SDimitry Andric Optional<SourceLocation> LocEnd, bool DeferRegion = false,
589a199699SDimitry Andric bool GapRegion = false)
599a199699SDimitry Andric : Count(Count), LocStart(LocStart), LocEnd(LocEnd),
609a199699SDimitry Andric DeferRegion(DeferRegion), GapRegion(GapRegion) {}
6139d628a0SDimitry Andric
getCounter() const6239d628a0SDimitry Andric const Counter &getCounter() const { return Count; }
6339d628a0SDimitry Andric
setCounter(Counter C)6433956c43SDimitry Andric void setCounter(Counter C) { Count = C; }
6539d628a0SDimitry Andric
hasStartLoc() const6633956c43SDimitry Andric bool hasStartLoc() const { return LocStart.hasValue(); }
6733956c43SDimitry Andric
setStartLoc(SourceLocation Loc)6833956c43SDimitry Andric void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
6933956c43SDimitry Andric
getBeginLoc() const704ba319b5SDimitry Andric SourceLocation getBeginLoc() const {
7133956c43SDimitry Andric assert(LocStart && "Region has no start location");
7233956c43SDimitry Andric return *LocStart;
7339d628a0SDimitry Andric }
7439d628a0SDimitry Andric
hasEndLoc() const7533956c43SDimitry Andric bool hasEndLoc() const { return LocEnd.hasValue(); }
7639d628a0SDimitry Andric
setEndLoc(SourceLocation Loc)774ba319b5SDimitry Andric void setEndLoc(SourceLocation Loc) {
784ba319b5SDimitry Andric assert(Loc.isValid() && "Setting an invalid end location");
794ba319b5SDimitry Andric LocEnd = Loc;
804ba319b5SDimitry Andric }
8139d628a0SDimitry Andric
getEndLoc() const820623d748SDimitry Andric SourceLocation getEndLoc() const {
8333956c43SDimitry Andric assert(LocEnd && "Region has no end location");
8433956c43SDimitry Andric return *LocEnd;
8539d628a0SDimitry Andric }
869a199699SDimitry Andric
isDeferred() const879a199699SDimitry Andric bool isDeferred() const { return DeferRegion; }
889a199699SDimitry Andric
setDeferred(bool Deferred)899a199699SDimitry Andric void setDeferred(bool Deferred) { DeferRegion = Deferred; }
909a199699SDimitry Andric
isGap() const919a199699SDimitry Andric bool isGap() const { return GapRegion; }
929a199699SDimitry Andric
setGap(bool Gap)939a199699SDimitry Andric void setGap(bool Gap) { GapRegion = Gap; }
949a199699SDimitry Andric };
959a199699SDimitry Andric
969a199699SDimitry Andric /// Spelling locations for the start and end of a source region.
979a199699SDimitry Andric struct SpellingRegion {
989a199699SDimitry Andric /// The line where the region starts.
999a199699SDimitry Andric unsigned LineStart;
1009a199699SDimitry Andric
1019a199699SDimitry Andric /// The column where the region starts.
1029a199699SDimitry Andric unsigned ColumnStart;
1039a199699SDimitry Andric
1049a199699SDimitry Andric /// The line where the region ends.
1059a199699SDimitry Andric unsigned LineEnd;
1069a199699SDimitry Andric
1079a199699SDimitry Andric /// The column where the region ends.
1089a199699SDimitry Andric unsigned ColumnEnd;
1099a199699SDimitry Andric
SpellingRegion__anonc2ccc9df0111::SpellingRegion1109a199699SDimitry Andric SpellingRegion(SourceManager &SM, SourceLocation LocStart,
1119a199699SDimitry Andric SourceLocation LocEnd) {
1129a199699SDimitry Andric LineStart = SM.getSpellingLineNumber(LocStart);
1139a199699SDimitry Andric ColumnStart = SM.getSpellingColumnNumber(LocStart);
1149a199699SDimitry Andric LineEnd = SM.getSpellingLineNumber(LocEnd);
1159a199699SDimitry Andric ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
1169a199699SDimitry Andric }
1179a199699SDimitry Andric
SpellingRegion__anonc2ccc9df0111::SpellingRegion1189a199699SDimitry Andric SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
119*b5893f02SDimitry Andric : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
1209a199699SDimitry Andric
1219a199699SDimitry Andric /// Check if the start and end locations appear in source order, i.e
1229a199699SDimitry Andric /// top->bottom, left->right.
isInSourceOrder__anonc2ccc9df0111::SpellingRegion1239a199699SDimitry Andric bool isInSourceOrder() const {
1249a199699SDimitry Andric return (LineStart < LineEnd) ||
1259a199699SDimitry Andric (LineStart == LineEnd && ColumnStart <= ColumnEnd);
1269a199699SDimitry Andric }
12739d628a0SDimitry Andric };
12839d628a0SDimitry Andric
1294ba319b5SDimitry Andric /// Provides the common functionality for the different
13039d628a0SDimitry Andric /// coverage mapping region builders.
13139d628a0SDimitry Andric class CoverageMappingBuilder {
13239d628a0SDimitry Andric public:
13339d628a0SDimitry Andric CoverageMappingModuleGen &CVM;
13439d628a0SDimitry Andric SourceManager &SM;
13539d628a0SDimitry Andric const LangOptions &LangOpts;
13639d628a0SDimitry Andric
13739d628a0SDimitry Andric private:
1384ba319b5SDimitry Andric /// Map of clang's FileIDs to IDs used for coverage mapping.
13933956c43SDimitry Andric llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
14033956c43SDimitry Andric FileIDMapping;
14139d628a0SDimitry Andric
14239d628a0SDimitry Andric public:
1434ba319b5SDimitry Andric /// The coverage mapping regions for this function
14439d628a0SDimitry Andric llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
1454ba319b5SDimitry Andric /// The source mapping regions for this function.
14639d628a0SDimitry Andric std::vector<SourceMappingRegion> SourceRegions;
14739d628a0SDimitry Andric
1484ba319b5SDimitry Andric /// A set of regions which can be used as a filter.
14944290647SDimitry Andric ///
15044290647SDimitry Andric /// It is produced by emitExpansionRegions() and is used in
15144290647SDimitry Andric /// emitSourceRegions() to suppress producing code regions if
15244290647SDimitry Andric /// the same area is covered by expansion regions.
15344290647SDimitry Andric typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
15444290647SDimitry Andric SourceRegionFilter;
15544290647SDimitry Andric
CoverageMappingBuilder(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)15639d628a0SDimitry Andric CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
15739d628a0SDimitry Andric const LangOptions &LangOpts)
15833956c43SDimitry Andric : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
15939d628a0SDimitry Andric
1604ba319b5SDimitry Andric /// Return the precise end location for the given token.
getPreciseTokenLocEnd(SourceLocation Loc)16139d628a0SDimitry Andric SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
16233956c43SDimitry Andric // We avoid getLocForEndOfToken here, because it doesn't do what we want for
16333956c43SDimitry Andric // macro locations, which we just treat as expanded files.
16433956c43SDimitry Andric unsigned TokLen =
16533956c43SDimitry Andric Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
16633956c43SDimitry Andric return Loc.getLocWithOffset(TokLen);
16739d628a0SDimitry Andric }
16839d628a0SDimitry Andric
1694ba319b5SDimitry Andric /// Return the start location of an included file or expanded macro.
getStartOfFileOrMacro(SourceLocation Loc)17033956c43SDimitry Andric SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
17133956c43SDimitry Andric if (Loc.isMacroID())
17233956c43SDimitry Andric return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
17333956c43SDimitry Andric return SM.getLocForStartOfFile(SM.getFileID(Loc));
17439d628a0SDimitry Andric }
17539d628a0SDimitry Andric
1764ba319b5SDimitry Andric /// Return the end location of an included file or expanded macro.
getEndOfFileOrMacro(SourceLocation Loc)17733956c43SDimitry Andric SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
17833956c43SDimitry Andric if (Loc.isMacroID())
17933956c43SDimitry Andric return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
18033956c43SDimitry Andric SM.getFileOffset(Loc));
18133956c43SDimitry Andric return SM.getLocForEndOfFile(SM.getFileID(Loc));
18239d628a0SDimitry Andric }
18339d628a0SDimitry Andric
1844ba319b5SDimitry Andric /// Find out where the current file is included or macro is expanded.
getIncludeOrExpansionLoc(SourceLocation Loc)18533956c43SDimitry Andric SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
1864ba319b5SDimitry Andric return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
18733956c43SDimitry Andric : SM.getIncludeLoc(SM.getFileID(Loc));
18833956c43SDimitry Andric }
18933956c43SDimitry Andric
1904ba319b5SDimitry Andric /// Return true if \c Loc is a location in a built-in macro.
isInBuiltin(SourceLocation Loc)19133956c43SDimitry Andric bool isInBuiltin(SourceLocation Loc) {
19244290647SDimitry Andric return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
19333956c43SDimitry Andric }
19433956c43SDimitry Andric
1954ba319b5SDimitry Andric /// Check whether \c Loc is included or expanded from \c Parent.
isNestedIn(SourceLocation Loc,FileID Parent)196e7145dcbSDimitry Andric bool isNestedIn(SourceLocation Loc, FileID Parent) {
197e7145dcbSDimitry Andric do {
198e7145dcbSDimitry Andric Loc = getIncludeOrExpansionLoc(Loc);
199e7145dcbSDimitry Andric if (Loc.isInvalid())
200e7145dcbSDimitry Andric return false;
201e7145dcbSDimitry Andric } while (!SM.isInFileID(Loc, Parent));
202e7145dcbSDimitry Andric return true;
203e7145dcbSDimitry Andric }
204e7145dcbSDimitry Andric
2054ba319b5SDimitry Andric /// Get the start of \c S ignoring macro arguments and builtin macros.
getStart(const Stmt * S)20633956c43SDimitry Andric SourceLocation getStart(const Stmt *S) {
207*b5893f02SDimitry Andric SourceLocation Loc = S->getBeginLoc();
20833956c43SDimitry Andric while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
2094ba319b5SDimitry Andric Loc = SM.getImmediateExpansionRange(Loc).getBegin();
21033956c43SDimitry Andric return Loc;
21133956c43SDimitry Andric }
21233956c43SDimitry Andric
2134ba319b5SDimitry Andric /// Get the end of \c S ignoring macro arguments and builtin macros.
getEnd(const Stmt * S)21433956c43SDimitry Andric SourceLocation getEnd(const Stmt *S) {
215*b5893f02SDimitry Andric SourceLocation Loc = S->getEndLoc();
21633956c43SDimitry Andric while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
2174ba319b5SDimitry Andric Loc = SM.getImmediateExpansionRange(Loc).getBegin();
21833956c43SDimitry Andric return getPreciseTokenLocEnd(Loc);
21933956c43SDimitry Andric }
22033956c43SDimitry Andric
2214ba319b5SDimitry Andric /// Find the set of files we have regions for and assign IDs
22233956c43SDimitry Andric ///
22333956c43SDimitry Andric /// Fills \c Mapping with the virtual file mapping needed to write out
22433956c43SDimitry Andric /// coverage and collects the necessary file information to emit source and
22533956c43SDimitry Andric /// expansion regions.
gatherFileIDs(SmallVectorImpl<unsigned> & Mapping)22633956c43SDimitry Andric void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
22733956c43SDimitry Andric FileIDMapping.clear();
22833956c43SDimitry Andric
229e7145dcbSDimitry Andric llvm::SmallSet<FileID, 8> Visited;
23033956c43SDimitry Andric SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
23133956c43SDimitry Andric for (const auto &Region : SourceRegions) {
232*b5893f02SDimitry Andric SourceLocation Loc = Region.getBeginLoc();
23333956c43SDimitry Andric FileID File = SM.getFileID(Loc);
234e7145dcbSDimitry Andric if (!Visited.insert(File).second)
23533956c43SDimitry Andric continue;
236e7145dcbSDimitry Andric
237e7145dcbSDimitry Andric // Do not map FileID's associated with system headers.
238e7145dcbSDimitry Andric if (SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
239e7145dcbSDimitry Andric continue;
24033956c43SDimitry Andric
24133956c43SDimitry Andric unsigned Depth = 0;
24233956c43SDimitry Andric for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
2430623d748SDimitry Andric Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
24433956c43SDimitry Andric ++Depth;
24533956c43SDimitry Andric FileLocs.push_back(std::make_pair(Loc, Depth));
24633956c43SDimitry Andric }
24733956c43SDimitry Andric std::stable_sort(FileLocs.begin(), FileLocs.end(), llvm::less_second());
24833956c43SDimitry Andric
24933956c43SDimitry Andric for (const auto &FL : FileLocs) {
25033956c43SDimitry Andric SourceLocation Loc = FL.first;
25133956c43SDimitry Andric FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
25239d628a0SDimitry Andric auto Entry = SM.getFileEntryForID(SpellingFile);
25339d628a0SDimitry Andric if (!Entry)
25433956c43SDimitry Andric continue;
25539d628a0SDimitry Andric
25633956c43SDimitry Andric FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
25733956c43SDimitry Andric Mapping.push_back(CVM.getFileID(Entry));
25833956c43SDimitry Andric }
25939d628a0SDimitry Andric }
26039d628a0SDimitry Andric
2614ba319b5SDimitry Andric /// Get the coverage mapping file ID for \c Loc.
26233956c43SDimitry Andric ///
26333956c43SDimitry Andric /// If such file id doesn't exist, return None.
getCoverageFileID(SourceLocation Loc)26433956c43SDimitry Andric Optional<unsigned> getCoverageFileID(SourceLocation Loc) {
26533956c43SDimitry Andric auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
26633956c43SDimitry Andric if (Mapping != FileIDMapping.end())
26733956c43SDimitry Andric return Mapping->second.first;
26833956c43SDimitry Andric return None;
26939d628a0SDimitry Andric }
27039d628a0SDimitry Andric
2714ba319b5SDimitry Andric /// Gather all the regions that were skipped by the preprocessor
27239d628a0SDimitry Andric /// using the constructs like #if.
gatherSkippedRegions()27339d628a0SDimitry Andric void gatherSkippedRegions() {
27439d628a0SDimitry Andric /// An array of the minimum lineStarts and the maximum lineEnds
27539d628a0SDimitry Andric /// for mapping regions from the appropriate source files.
27639d628a0SDimitry Andric llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
27739d628a0SDimitry Andric FileLineRanges.resize(
27839d628a0SDimitry Andric FileIDMapping.size(),
27939d628a0SDimitry Andric std::make_pair(std::numeric_limits<unsigned>::max(), 0));
28039d628a0SDimitry Andric for (const auto &R : MappingRegions) {
28139d628a0SDimitry Andric FileLineRanges[R.FileID].first =
28239d628a0SDimitry Andric std::min(FileLineRanges[R.FileID].first, R.LineStart);
28339d628a0SDimitry Andric FileLineRanges[R.FileID].second =
28439d628a0SDimitry Andric std::max(FileLineRanges[R.FileID].second, R.LineEnd);
28539d628a0SDimitry Andric }
28639d628a0SDimitry Andric
28739d628a0SDimitry Andric auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
28839d628a0SDimitry Andric for (const auto &I : SkippedRanges) {
28939d628a0SDimitry Andric auto LocStart = I.getBegin();
29039d628a0SDimitry Andric auto LocEnd = I.getEnd();
29133956c43SDimitry Andric assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
29233956c43SDimitry Andric "region spans multiple files");
29339d628a0SDimitry Andric
29433956c43SDimitry Andric auto CovFileID = getCoverageFileID(LocStart);
29533956c43SDimitry Andric if (!CovFileID)
29639d628a0SDimitry Andric continue;
2979a199699SDimitry Andric SpellingRegion SR{SM, LocStart, LocEnd};
29833956c43SDimitry Andric auto Region = CounterMappingRegion::makeSkipped(
2999a199699SDimitry Andric *CovFileID, SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd);
30039d628a0SDimitry Andric // Make sure that we only collect the regions that are inside
3014ba319b5SDimitry Andric // the source code of this function.
30233956c43SDimitry Andric if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
30333956c43SDimitry Andric Region.LineEnd <= FileLineRanges[*CovFileID].second)
30439d628a0SDimitry Andric MappingRegions.push_back(Region);
30539d628a0SDimitry Andric }
30639d628a0SDimitry Andric }
30739d628a0SDimitry Andric
3084ba319b5SDimitry Andric /// Generate the coverage counter mapping regions from collected
30939d628a0SDimitry Andric /// source regions.
emitSourceRegions(const SourceRegionFilter & Filter)31044290647SDimitry Andric void emitSourceRegions(const SourceRegionFilter &Filter) {
31133956c43SDimitry Andric for (const auto &Region : SourceRegions) {
31233956c43SDimitry Andric assert(Region.hasEndLoc() && "incomplete region");
31339d628a0SDimitry Andric
314*b5893f02SDimitry Andric SourceLocation LocStart = Region.getBeginLoc();
3150623d748SDimitry Andric assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
31639d628a0SDimitry Andric
317e7145dcbSDimitry Andric // Ignore regions from system headers.
318e7145dcbSDimitry Andric if (SM.isInSystemHeader(SM.getSpellingLoc(LocStart)))
319e7145dcbSDimitry Andric continue;
320e7145dcbSDimitry Andric
32133956c43SDimitry Andric auto CovFileID = getCoverageFileID(LocStart);
32233956c43SDimitry Andric // Ignore regions that don't have a file, such as builtin macros.
32333956c43SDimitry Andric if (!CovFileID)
32439d628a0SDimitry Andric continue;
32539d628a0SDimitry Andric
32633956c43SDimitry Andric SourceLocation LocEnd = Region.getEndLoc();
32733956c43SDimitry Andric assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
32833956c43SDimitry Andric "region spans multiple files");
32933956c43SDimitry Andric
33044290647SDimitry Andric // Don't add code regions for the area covered by expansion regions.
33144290647SDimitry Andric // This not only suppresses redundant regions, but sometimes prevents
33244290647SDimitry Andric // creating regions with wrong counters if, for example, a statement's
33344290647SDimitry Andric // body ends at the end of a nested macro.
33444290647SDimitry Andric if (Filter.count(std::make_pair(LocStart, LocEnd)))
33544290647SDimitry Andric continue;
33644290647SDimitry Andric
3379a199699SDimitry Andric // Find the spelling locations for the mapping region.
3389a199699SDimitry Andric SpellingRegion SR{SM, LocStart, LocEnd};
3399a199699SDimitry Andric assert(SR.isInSourceOrder() && "region start and end out of order");
34039d628a0SDimitry Andric
3419a199699SDimitry Andric if (Region.isGap()) {
3429a199699SDimitry Andric MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
3439a199699SDimitry Andric Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
3449a199699SDimitry Andric SR.LineEnd, SR.ColumnEnd));
3459a199699SDimitry Andric } else {
34633956c43SDimitry Andric MappingRegions.push_back(CounterMappingRegion::makeRegion(
3479a199699SDimitry Andric Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
3489a199699SDimitry Andric SR.LineEnd, SR.ColumnEnd));
3499a199699SDimitry Andric }
35033956c43SDimitry Andric }
35133956c43SDimitry Andric }
35233956c43SDimitry Andric
3534ba319b5SDimitry Andric /// Generate expansion regions for each virtual file we've seen.
emitExpansionRegions()35444290647SDimitry Andric SourceRegionFilter emitExpansionRegions() {
35544290647SDimitry Andric SourceRegionFilter Filter;
35633956c43SDimitry Andric for (const auto &FM : FileIDMapping) {
35733956c43SDimitry Andric SourceLocation ExpandedLoc = FM.second.second;
35833956c43SDimitry Andric SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
35933956c43SDimitry Andric if (ParentLoc.isInvalid())
36039d628a0SDimitry Andric continue;
36139d628a0SDimitry Andric
36233956c43SDimitry Andric auto ParentFileID = getCoverageFileID(ParentLoc);
36333956c43SDimitry Andric if (!ParentFileID)
36433956c43SDimitry Andric continue;
36533956c43SDimitry Andric auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
36633956c43SDimitry Andric assert(ExpandedFileID && "expansion in uncovered file");
36733956c43SDimitry Andric
36833956c43SDimitry Andric SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
36933956c43SDimitry Andric assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
37033956c43SDimitry Andric "region spans multiple files");
37144290647SDimitry Andric Filter.insert(std::make_pair(ParentLoc, LocEnd));
37233956c43SDimitry Andric
3739a199699SDimitry Andric SpellingRegion SR{SM, ParentLoc, LocEnd};
3749a199699SDimitry Andric assert(SR.isInSourceOrder() && "region start and end out of order");
37533956c43SDimitry Andric MappingRegions.push_back(CounterMappingRegion::makeExpansion(
3769a199699SDimitry Andric *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
3779a199699SDimitry Andric SR.LineEnd, SR.ColumnEnd));
37839d628a0SDimitry Andric }
37944290647SDimitry Andric return Filter;
38039d628a0SDimitry Andric }
38139d628a0SDimitry Andric };
38239d628a0SDimitry Andric
3834ba319b5SDimitry Andric /// Creates unreachable coverage regions for the functions that
38439d628a0SDimitry Andric /// are not emitted.
38539d628a0SDimitry Andric struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
EmptyCoverageMappingBuilder__anonc2ccc9df0111::EmptyCoverageMappingBuilder38639d628a0SDimitry Andric EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
38739d628a0SDimitry Andric const LangOptions &LangOpts)
38839d628a0SDimitry Andric : CoverageMappingBuilder(CVM, SM, LangOpts) {}
38939d628a0SDimitry Andric
VisitDecl__anonc2ccc9df0111::EmptyCoverageMappingBuilder39039d628a0SDimitry Andric void VisitDecl(const Decl *D) {
39139d628a0SDimitry Andric if (!D->hasBody())
39239d628a0SDimitry Andric return;
39339d628a0SDimitry Andric auto Body = D->getBody();
394e7145dcbSDimitry Andric SourceLocation Start = getStart(Body);
395e7145dcbSDimitry Andric SourceLocation End = getEnd(Body);
396e7145dcbSDimitry Andric if (!SM.isWrittenInSameFile(Start, End)) {
397e7145dcbSDimitry Andric // Walk up to find the common ancestor.
398e7145dcbSDimitry Andric // Correct the locations accordingly.
399e7145dcbSDimitry Andric FileID StartFileID = SM.getFileID(Start);
400e7145dcbSDimitry Andric FileID EndFileID = SM.getFileID(End);
401e7145dcbSDimitry Andric while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
402e7145dcbSDimitry Andric Start = getIncludeOrExpansionLoc(Start);
403e7145dcbSDimitry Andric assert(Start.isValid() &&
404e7145dcbSDimitry Andric "Declaration start location not nested within a known region");
405e7145dcbSDimitry Andric StartFileID = SM.getFileID(Start);
406e7145dcbSDimitry Andric }
407e7145dcbSDimitry Andric while (StartFileID != EndFileID) {
408e7145dcbSDimitry Andric End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
409e7145dcbSDimitry Andric assert(End.isValid() &&
410e7145dcbSDimitry Andric "Declaration end location not nested within a known region");
411e7145dcbSDimitry Andric EndFileID = SM.getFileID(End);
412e7145dcbSDimitry Andric }
413e7145dcbSDimitry Andric }
414e7145dcbSDimitry Andric SourceRegions.emplace_back(Counter(), Start, End);
41539d628a0SDimitry Andric }
41639d628a0SDimitry Andric
4174ba319b5SDimitry Andric /// Write the mapping data to the output stream
write__anonc2ccc9df0111::EmptyCoverageMappingBuilder41839d628a0SDimitry Andric void write(llvm::raw_ostream &OS) {
41939d628a0SDimitry Andric SmallVector<unsigned, 16> FileIDMapping;
42033956c43SDimitry Andric gatherFileIDs(FileIDMapping);
42144290647SDimitry Andric emitSourceRegions(SourceRegionFilter());
42239d628a0SDimitry Andric
42352449daeSDimitry Andric if (MappingRegions.empty())
42452449daeSDimitry Andric return;
42552449daeSDimitry Andric
42639d628a0SDimitry Andric CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
42739d628a0SDimitry Andric Writer.write(OS);
42839d628a0SDimitry Andric }
42939d628a0SDimitry Andric };
43039d628a0SDimitry Andric
4314ba319b5SDimitry Andric /// A StmtVisitor that creates coverage mapping regions which map
43239d628a0SDimitry Andric /// from the source code locations to the PGO counters.
43339d628a0SDimitry Andric struct CounterCoverageMappingBuilder
43439d628a0SDimitry Andric : public CoverageMappingBuilder,
43539d628a0SDimitry Andric public ConstStmtVisitor<CounterCoverageMappingBuilder> {
4364ba319b5SDimitry Andric /// The map of statements to count values.
43739d628a0SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
43839d628a0SDimitry Andric
4394ba319b5SDimitry Andric /// A stack of currently live regions.
44033956c43SDimitry Andric std::vector<SourceMappingRegion> RegionStack;
44139d628a0SDimitry Andric
4429a199699SDimitry Andric /// The currently deferred region: its end location and count can be set once
4439a199699SDimitry Andric /// its parent has been popped from the region stack.
4449a199699SDimitry Andric Optional<SourceMappingRegion> DeferredRegion;
4459a199699SDimitry Andric
44639d628a0SDimitry Andric CounterExpressionBuilder Builder;
44739d628a0SDimitry Andric
4484ba319b5SDimitry Andric /// A location in the most recently visited file or macro.
44933956c43SDimitry Andric ///
45033956c43SDimitry Andric /// This is used to adjust the active source regions appropriately when
45133956c43SDimitry Andric /// expressions cross file or macro boundaries.
45233956c43SDimitry Andric SourceLocation MostRecentLocation;
45333956c43SDimitry Andric
4549a199699SDimitry Andric /// Location of the last terminated region.
4559a199699SDimitry Andric Optional<std::pair<SourceLocation, size_t>> LastTerminatedRegion;
4569a199699SDimitry Andric
4574ba319b5SDimitry Andric /// Return a counter for the subtraction of \c RHS from \c LHS
subtractCounters__anonc2ccc9df0111::CounterCoverageMappingBuilder45839d628a0SDimitry Andric Counter subtractCounters(Counter LHS, Counter RHS) {
45939d628a0SDimitry Andric return Builder.subtract(LHS, RHS);
46039d628a0SDimitry Andric }
46139d628a0SDimitry Andric
4624ba319b5SDimitry Andric /// Return a counter for the sum of \c LHS and \c RHS.
addCounters__anonc2ccc9df0111::CounterCoverageMappingBuilder46339d628a0SDimitry Andric Counter addCounters(Counter LHS, Counter RHS) {
46439d628a0SDimitry Andric return Builder.add(LHS, RHS);
46539d628a0SDimitry Andric }
46639d628a0SDimitry Andric
addCounters__anonc2ccc9df0111::CounterCoverageMappingBuilder46733956c43SDimitry Andric Counter addCounters(Counter C1, Counter C2, Counter C3) {
46833956c43SDimitry Andric return addCounters(addCounters(C1, C2), C3);
46933956c43SDimitry Andric }
47033956c43SDimitry Andric
4714ba319b5SDimitry Andric /// Return the region counter for the given statement.
47233956c43SDimitry Andric ///
47339d628a0SDimitry Andric /// This should only be called on statements that have a dedicated counter.
getRegionCounter__anonc2ccc9df0111::CounterCoverageMappingBuilder47433956c43SDimitry Andric Counter getRegionCounter(const Stmt *S) {
47533956c43SDimitry Andric return Counter::getCounter(CounterMap[S]);
47639d628a0SDimitry Andric }
47739d628a0SDimitry Andric
4784ba319b5SDimitry Andric /// Push a region onto the stack.
47933956c43SDimitry Andric ///
48033956c43SDimitry Andric /// Returns the index on the stack where the region was pushed. This can be
48133956c43SDimitry Andric /// used with popRegions to exit a "scope", ending the region that was pushed.
pushRegion__anonc2ccc9df0111::CounterCoverageMappingBuilder48233956c43SDimitry Andric size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
48333956c43SDimitry Andric Optional<SourceLocation> EndLoc = None) {
4849a199699SDimitry Andric if (StartLoc) {
48533956c43SDimitry Andric MostRecentLocation = *StartLoc;
4869a199699SDimitry Andric completeDeferred(Count, MostRecentLocation);
4879a199699SDimitry Andric }
48833956c43SDimitry Andric RegionStack.emplace_back(Count, StartLoc, EndLoc);
48939d628a0SDimitry Andric
49033956c43SDimitry Andric return RegionStack.size() - 1;
49139d628a0SDimitry Andric }
49239d628a0SDimitry Andric
4939a199699SDimitry Andric /// Complete any pending deferred region by setting its end location and
4949a199699SDimitry Andric /// count, and then pushing it onto the region stack.
completeDeferred__anonc2ccc9df0111::CounterCoverageMappingBuilder4959a199699SDimitry Andric size_t completeDeferred(Counter Count, SourceLocation DeferredEndLoc) {
4969a199699SDimitry Andric size_t Index = RegionStack.size();
4979a199699SDimitry Andric if (!DeferredRegion)
4989a199699SDimitry Andric return Index;
4999a199699SDimitry Andric
5009a199699SDimitry Andric // Consume the pending region.
5019a199699SDimitry Andric SourceMappingRegion DR = DeferredRegion.getValue();
5029a199699SDimitry Andric DeferredRegion = None;
5039a199699SDimitry Andric
5049a199699SDimitry Andric // If the region ends in an expansion, find the expansion site.
505*b5893f02SDimitry Andric FileID StartFile = SM.getFileID(DR.getBeginLoc());
5069a199699SDimitry Andric if (SM.getFileID(DeferredEndLoc) != StartFile) {
5079a199699SDimitry Andric if (isNestedIn(DeferredEndLoc, StartFile)) {
5089a199699SDimitry Andric do {
5099a199699SDimitry Andric DeferredEndLoc = getIncludeOrExpansionLoc(DeferredEndLoc);
5109a199699SDimitry Andric } while (StartFile != SM.getFileID(DeferredEndLoc));
5119a199699SDimitry Andric } else {
5129a199699SDimitry Andric return Index;
5139a199699SDimitry Andric }
5149a199699SDimitry Andric }
5159a199699SDimitry Andric
5169a199699SDimitry Andric // The parent of this deferred region ends where the containing decl ends,
5179a199699SDimitry Andric // so the region isn't useful.
518*b5893f02SDimitry Andric if (DR.getBeginLoc() == DeferredEndLoc)
5199a199699SDimitry Andric return Index;
5209a199699SDimitry Andric
5219a199699SDimitry Andric // If we're visiting statements in non-source order (e.g switch cases or
5229a199699SDimitry Andric // a loop condition) we can't construct a sensible deferred region.
523*b5893f02SDimitry Andric if (!SpellingRegion(SM, DR.getBeginLoc(), DeferredEndLoc).isInSourceOrder())
5249a199699SDimitry Andric return Index;
5259a199699SDimitry Andric
5269a199699SDimitry Andric DR.setGap(true);
5279a199699SDimitry Andric DR.setCounter(Count);
5289a199699SDimitry Andric DR.setEndLoc(DeferredEndLoc);
5299a199699SDimitry Andric handleFileExit(DeferredEndLoc);
5309a199699SDimitry Andric RegionStack.push_back(DR);
5319a199699SDimitry Andric return Index;
5329a199699SDimitry Andric }
5339a199699SDimitry Andric
5349a199699SDimitry Andric /// Complete a deferred region created after a terminated region at the
5359a199699SDimitry Andric /// top-level.
completeTopLevelDeferredRegion__anonc2ccc9df0111::CounterCoverageMappingBuilder5369a199699SDimitry Andric void completeTopLevelDeferredRegion(Counter Count,
5379a199699SDimitry Andric SourceLocation DeferredEndLoc) {
5389a199699SDimitry Andric if (DeferredRegion || !LastTerminatedRegion)
5399a199699SDimitry Andric return;
5409a199699SDimitry Andric
5419a199699SDimitry Andric if (LastTerminatedRegion->second != RegionStack.size())
5429a199699SDimitry Andric return;
5439a199699SDimitry Andric
5449a199699SDimitry Andric SourceLocation Start = LastTerminatedRegion->first;
5459a199699SDimitry Andric if (SM.getFileID(Start) != SM.getMainFileID())
5469a199699SDimitry Andric return;
5479a199699SDimitry Andric
5489a199699SDimitry Andric SourceMappingRegion DR = RegionStack.back();
5499a199699SDimitry Andric DR.setStartLoc(Start);
5509a199699SDimitry Andric DR.setDeferred(false);
5519a199699SDimitry Andric DeferredRegion = DR;
5529a199699SDimitry Andric completeDeferred(Count, DeferredEndLoc);
5539a199699SDimitry Andric }
5549a199699SDimitry Andric
locationDepth__anonc2ccc9df0111::CounterCoverageMappingBuilder5554ba319b5SDimitry Andric size_t locationDepth(SourceLocation Loc) {
5564ba319b5SDimitry Andric size_t Depth = 0;
5574ba319b5SDimitry Andric while (Loc.isValid()) {
5584ba319b5SDimitry Andric Loc = getIncludeOrExpansionLoc(Loc);
5594ba319b5SDimitry Andric Depth++;
5604ba319b5SDimitry Andric }
5614ba319b5SDimitry Andric return Depth;
5624ba319b5SDimitry Andric }
5634ba319b5SDimitry Andric
5644ba319b5SDimitry Andric /// Pop regions from the stack into the function's list of regions.
56533956c43SDimitry Andric ///
56633956c43SDimitry Andric /// Adds all regions from \c ParentIndex to the top of the stack to the
56733956c43SDimitry Andric /// function's \c SourceRegions.
popRegions__anonc2ccc9df0111::CounterCoverageMappingBuilder56833956c43SDimitry Andric void popRegions(size_t ParentIndex) {
56933956c43SDimitry Andric assert(RegionStack.size() >= ParentIndex && "parent not in stack");
5709a199699SDimitry Andric bool ParentOfDeferredRegion = false;
57133956c43SDimitry Andric while (RegionStack.size() > ParentIndex) {
57233956c43SDimitry Andric SourceMappingRegion &Region = RegionStack.back();
57333956c43SDimitry Andric if (Region.hasStartLoc()) {
574*b5893f02SDimitry Andric SourceLocation StartLoc = Region.getBeginLoc();
57533956c43SDimitry Andric SourceLocation EndLoc = Region.hasEndLoc()
57633956c43SDimitry Andric ? Region.getEndLoc()
57733956c43SDimitry Andric : RegionStack[ParentIndex].getEndLoc();
5784ba319b5SDimitry Andric size_t StartDepth = locationDepth(StartLoc);
5794ba319b5SDimitry Andric size_t EndDepth = locationDepth(EndLoc);
58033956c43SDimitry Andric while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
5814ba319b5SDimitry Andric bool UnnestStart = StartDepth >= EndDepth;
5824ba319b5SDimitry Andric bool UnnestEnd = EndDepth >= StartDepth;
5834ba319b5SDimitry Andric if (UnnestEnd) {
58433956c43SDimitry Andric // The region ends in a nested file or macro expansion. Create a
58533956c43SDimitry Andric // separate region for each expansion.
58633956c43SDimitry Andric SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
58733956c43SDimitry Andric assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
58833956c43SDimitry Andric
58944290647SDimitry Andric if (!isRegionAlreadyAdded(NestedLoc, EndLoc))
59033956c43SDimitry Andric SourceRegions.emplace_back(Region.getCounter(), NestedLoc, EndLoc);
59133956c43SDimitry Andric
59233956c43SDimitry Andric EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
5930623d748SDimitry Andric if (EndLoc.isInvalid())
5940623d748SDimitry Andric llvm::report_fatal_error("File exit not handled before popRegions");
5954ba319b5SDimitry Andric EndDepth--;
59633956c43SDimitry Andric }
5974ba319b5SDimitry Andric if (UnnestStart) {
5984ba319b5SDimitry Andric // The region begins in a nested file or macro expansion. Create a
5994ba319b5SDimitry Andric // separate region for each expansion.
6004ba319b5SDimitry Andric SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
6014ba319b5SDimitry Andric assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
6024ba319b5SDimitry Andric
6034ba319b5SDimitry Andric if (!isRegionAlreadyAdded(StartLoc, NestedLoc))
6044ba319b5SDimitry Andric SourceRegions.emplace_back(Region.getCounter(), StartLoc, NestedLoc);
6054ba319b5SDimitry Andric
6064ba319b5SDimitry Andric StartLoc = getIncludeOrExpansionLoc(StartLoc);
6074ba319b5SDimitry Andric if (StartLoc.isInvalid())
6084ba319b5SDimitry Andric llvm::report_fatal_error("File exit not handled before popRegions");
6094ba319b5SDimitry Andric StartDepth--;
6104ba319b5SDimitry Andric }
6114ba319b5SDimitry Andric }
6124ba319b5SDimitry Andric Region.setStartLoc(StartLoc);
61333956c43SDimitry Andric Region.setEndLoc(EndLoc);
61433956c43SDimitry Andric
61533956c43SDimitry Andric MostRecentLocation = EndLoc;
61633956c43SDimitry Andric // If this region happens to span an entire expansion, we need to make
61733956c43SDimitry Andric // sure we don't overlap the parent region with it.
61833956c43SDimitry Andric if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
61933956c43SDimitry Andric EndLoc == getEndOfFileOrMacro(EndLoc))
62033956c43SDimitry Andric MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
62133956c43SDimitry Andric
622*b5893f02SDimitry Andric assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
6239a199699SDimitry Andric assert(SpellingRegion(SM, Region).isInSourceOrder());
6240623d748SDimitry Andric SourceRegions.push_back(Region);
6259a199699SDimitry Andric
6269a199699SDimitry Andric if (ParentOfDeferredRegion) {
6279a199699SDimitry Andric ParentOfDeferredRegion = false;
6289a199699SDimitry Andric
6299a199699SDimitry Andric // If there's an existing deferred region, keep the old one, because
6309a199699SDimitry Andric // it means there are two consecutive returns (or a similar pattern).
6319a199699SDimitry Andric if (!DeferredRegion.hasValue() &&
6329a199699SDimitry Andric // File IDs aren't gathered within macro expansions, so it isn't
6339a199699SDimitry Andric // useful to try and create a deferred region inside of one.
6349a199699SDimitry Andric !EndLoc.isMacroID())
6359a199699SDimitry Andric DeferredRegion =
6369a199699SDimitry Andric SourceMappingRegion(Counter::getZero(), EndLoc, None);
6379a199699SDimitry Andric }
6389a199699SDimitry Andric } else if (Region.isDeferred()) {
6399a199699SDimitry Andric assert(!ParentOfDeferredRegion && "Consecutive deferred regions");
6409a199699SDimitry Andric ParentOfDeferredRegion = true;
64133956c43SDimitry Andric }
64233956c43SDimitry Andric RegionStack.pop_back();
6439a199699SDimitry Andric
6449a199699SDimitry Andric // If the zero region pushed after the last terminated region no longer
6459a199699SDimitry Andric // exists, clear its cached information.
6469a199699SDimitry Andric if (LastTerminatedRegion &&
6479a199699SDimitry Andric RegionStack.size() < LastTerminatedRegion->second)
6489a199699SDimitry Andric LastTerminatedRegion = None;
64933956c43SDimitry Andric }
6509a199699SDimitry Andric assert(!ParentOfDeferredRegion && "Deferred region with no parent");
65139d628a0SDimitry Andric }
65239d628a0SDimitry Andric
6534ba319b5SDimitry Andric /// Return the currently active region.
getRegion__anonc2ccc9df0111::CounterCoverageMappingBuilder65433956c43SDimitry Andric SourceMappingRegion &getRegion() {
65533956c43SDimitry Andric assert(!RegionStack.empty() && "statement has no region");
65633956c43SDimitry Andric return RegionStack.back();
65739d628a0SDimitry Andric }
65839d628a0SDimitry Andric
659*b5893f02SDimitry Andric /// Propagate counts through the children of \p S if \p VisitChildren is true.
660*b5893f02SDimitry Andric /// Otherwise, only emit a count for \p S itself.
propagateCounts__anonc2ccc9df0111::CounterCoverageMappingBuilder661*b5893f02SDimitry Andric Counter propagateCounts(Counter TopCount, const Stmt *S,
662*b5893f02SDimitry Andric bool VisitChildren = true) {
6639a199699SDimitry Andric SourceLocation StartLoc = getStart(S);
6649a199699SDimitry Andric SourceLocation EndLoc = getEnd(S);
6659a199699SDimitry Andric size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
666*b5893f02SDimitry Andric if (VisitChildren)
66733956c43SDimitry Andric Visit(S);
66833956c43SDimitry Andric Counter ExitCount = getRegion().getCounter();
66933956c43SDimitry Andric popRegions(Index);
670e7145dcbSDimitry Andric
671e7145dcbSDimitry Andric // The statement may be spanned by an expansion. Make sure we handle a file
672e7145dcbSDimitry Andric // exit out of this expansion before moving to the next statement.
673*b5893f02SDimitry Andric if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
6749a199699SDimitry Andric MostRecentLocation = EndLoc;
675e7145dcbSDimitry Andric
67633956c43SDimitry Andric return ExitCount;
67739d628a0SDimitry Andric }
67839d628a0SDimitry Andric
6794ba319b5SDimitry Andric /// Check whether a region with bounds \c StartLoc and \c EndLoc
680e7145dcbSDimitry Andric /// is already added to \c SourceRegions.
isRegionAlreadyAdded__anonc2ccc9df0111::CounterCoverageMappingBuilder681e7145dcbSDimitry Andric bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc) {
682e7145dcbSDimitry Andric return SourceRegions.rend() !=
683e7145dcbSDimitry Andric std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
684e7145dcbSDimitry Andric [&](const SourceMappingRegion &Region) {
685*b5893f02SDimitry Andric return Region.getBeginLoc() == StartLoc &&
686e7145dcbSDimitry Andric Region.getEndLoc() == EndLoc;
687e7145dcbSDimitry Andric });
688e7145dcbSDimitry Andric }
689e7145dcbSDimitry Andric
6904ba319b5SDimitry Andric /// Adjust the most recently visited location to \c EndLoc.
69133956c43SDimitry Andric ///
69233956c43SDimitry Andric /// This should be used after visiting any statements in non-source order.
adjustForOutOfOrderTraversal__anonc2ccc9df0111::CounterCoverageMappingBuilder69333956c43SDimitry Andric void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
69433956c43SDimitry Andric MostRecentLocation = EndLoc;
695e7145dcbSDimitry Andric // The code region for a whole macro is created in handleFileExit() when
696e7145dcbSDimitry Andric // it detects exiting of the virtual file of that macro. If we visited
697e7145dcbSDimitry Andric // statements in non-source order, we might already have such a region
698e7145dcbSDimitry Andric // added, for example, if a body of a loop is divided among multiple
699e7145dcbSDimitry Andric // macros. Avoid adding duplicate regions in such case.
70033956c43SDimitry Andric if (getRegion().hasEndLoc() &&
701e7145dcbSDimitry Andric MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
702e7145dcbSDimitry Andric isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
703e7145dcbSDimitry Andric MostRecentLocation))
70433956c43SDimitry Andric MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
70539d628a0SDimitry Andric }
70639d628a0SDimitry Andric
7074ba319b5SDimitry Andric /// Adjust regions and state when \c NewLoc exits a file.
70833956c43SDimitry Andric ///
70933956c43SDimitry Andric /// If moving from our most recently tracked location to \c NewLoc exits any
71033956c43SDimitry Andric /// files, this adjusts our current region stack and creates the file regions
71133956c43SDimitry Andric /// for the exited file.
handleFileExit__anonc2ccc9df0111::CounterCoverageMappingBuilder71233956c43SDimitry Andric void handleFileExit(SourceLocation NewLoc) {
7133dac3a9bSDimitry Andric if (NewLoc.isInvalid() ||
7143dac3a9bSDimitry Andric SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
71533956c43SDimitry Andric return;
71633956c43SDimitry Andric
71733956c43SDimitry Andric // If NewLoc is not in a file that contains MostRecentLocation, walk up to
71833956c43SDimitry Andric // find the common ancestor.
71933956c43SDimitry Andric SourceLocation LCA = NewLoc;
72033956c43SDimitry Andric FileID ParentFile = SM.getFileID(LCA);
72133956c43SDimitry Andric while (!isNestedIn(MostRecentLocation, ParentFile)) {
72233956c43SDimitry Andric LCA = getIncludeOrExpansionLoc(LCA);
72333956c43SDimitry Andric if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
72433956c43SDimitry Andric // Since there isn't a common ancestor, no file was exited. We just need
72533956c43SDimitry Andric // to adjust our location to the new file.
72633956c43SDimitry Andric MostRecentLocation = NewLoc;
72733956c43SDimitry Andric return;
72833956c43SDimitry Andric }
72933956c43SDimitry Andric ParentFile = SM.getFileID(LCA);
73039d628a0SDimitry Andric }
73139d628a0SDimitry Andric
73233956c43SDimitry Andric llvm::SmallSet<SourceLocation, 8> StartLocs;
73333956c43SDimitry Andric Optional<Counter> ParentCounter;
7340623d748SDimitry Andric for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
7350623d748SDimitry Andric if (!I.hasStartLoc())
73633956c43SDimitry Andric continue;
737*b5893f02SDimitry Andric SourceLocation Loc = I.getBeginLoc();
73833956c43SDimitry Andric if (!isNestedIn(Loc, ParentFile)) {
7390623d748SDimitry Andric ParentCounter = I.getCounter();
74033956c43SDimitry Andric break;
74139d628a0SDimitry Andric }
74233956c43SDimitry Andric
74333956c43SDimitry Andric while (!SM.isInFileID(Loc, ParentFile)) {
74433956c43SDimitry Andric // The most nested region for each start location is the one with the
74533956c43SDimitry Andric // correct count. We avoid creating redundant regions by stopping once
74633956c43SDimitry Andric // we've seen this region.
74733956c43SDimitry Andric if (StartLocs.insert(Loc).second)
7480623d748SDimitry Andric SourceRegions.emplace_back(I.getCounter(), Loc,
74933956c43SDimitry Andric getEndOfFileOrMacro(Loc));
75033956c43SDimitry Andric Loc = getIncludeOrExpansionLoc(Loc);
75139d628a0SDimitry Andric }
7520623d748SDimitry Andric I.setStartLoc(getPreciseTokenLocEnd(Loc));
75333956c43SDimitry Andric }
75433956c43SDimitry Andric
75533956c43SDimitry Andric if (ParentCounter) {
75633956c43SDimitry Andric // If the file is contained completely by another region and doesn't
75733956c43SDimitry Andric // immediately start its own region, the whole file gets a region
75833956c43SDimitry Andric // corresponding to the parent.
75933956c43SDimitry Andric SourceLocation Loc = MostRecentLocation;
76033956c43SDimitry Andric while (isNestedIn(Loc, ParentFile)) {
76133956c43SDimitry Andric SourceLocation FileStart = getStartOfFileOrMacro(Loc);
7629a199699SDimitry Andric if (StartLocs.insert(FileStart).second) {
76333956c43SDimitry Andric SourceRegions.emplace_back(*ParentCounter, FileStart,
76433956c43SDimitry Andric getEndOfFileOrMacro(Loc));
7659a199699SDimitry Andric assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder());
7669a199699SDimitry Andric }
76733956c43SDimitry Andric Loc = getIncludeOrExpansionLoc(Loc);
76833956c43SDimitry Andric }
76933956c43SDimitry Andric }
77033956c43SDimitry Andric
77133956c43SDimitry Andric MostRecentLocation = NewLoc;
77233956c43SDimitry Andric }
77333956c43SDimitry Andric
7744ba319b5SDimitry Andric /// Ensure that \c S is included in the current region.
extendRegion__anonc2ccc9df0111::CounterCoverageMappingBuilder77533956c43SDimitry Andric void extendRegion(const Stmt *S) {
77633956c43SDimitry Andric SourceMappingRegion &Region = getRegion();
77733956c43SDimitry Andric SourceLocation StartLoc = getStart(S);
77833956c43SDimitry Andric
77933956c43SDimitry Andric handleFileExit(StartLoc);
78033956c43SDimitry Andric if (!Region.hasStartLoc())
78133956c43SDimitry Andric Region.setStartLoc(StartLoc);
7829a199699SDimitry Andric
7839a199699SDimitry Andric completeDeferred(Region.getCounter(), StartLoc);
78433956c43SDimitry Andric }
78533956c43SDimitry Andric
7864ba319b5SDimitry Andric /// Mark \c S as a terminator, starting a zero region.
terminateRegion__anonc2ccc9df0111::CounterCoverageMappingBuilder78733956c43SDimitry Andric void terminateRegion(const Stmt *S) {
78833956c43SDimitry Andric extendRegion(S);
78933956c43SDimitry Andric SourceMappingRegion &Region = getRegion();
7909a199699SDimitry Andric SourceLocation EndLoc = getEnd(S);
79133956c43SDimitry Andric if (!Region.hasEndLoc())
7929a199699SDimitry Andric Region.setEndLoc(EndLoc);
79333956c43SDimitry Andric pushRegion(Counter::getZero());
7949a199699SDimitry Andric auto &ZeroRegion = getRegion();
7959a199699SDimitry Andric ZeroRegion.setDeferred(true);
7969a199699SDimitry Andric LastTerminatedRegion = {EndLoc, RegionStack.size()};
7979a199699SDimitry Andric }
7989a199699SDimitry Andric
7999a199699SDimitry Andric /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
findGapAreaBetween__anonc2ccc9df0111::CounterCoverageMappingBuilder8009a199699SDimitry Andric Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
8019a199699SDimitry Andric SourceLocation BeforeLoc) {
8029a199699SDimitry Andric // If the start and end locations of the gap are both within the same macro
8039a199699SDimitry Andric // file, the range may not be in source order.
8049a199699SDimitry Andric if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
8059a199699SDimitry Andric return None;
8069a199699SDimitry Andric if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc))
8079a199699SDimitry Andric return None;
8089a199699SDimitry Andric return {{AfterLoc, BeforeLoc}};
8099a199699SDimitry Andric }
8109a199699SDimitry Andric
8119a199699SDimitry Andric /// Find the source range after \p AfterStmt and before \p BeforeStmt.
findGapAreaBetween__anonc2ccc9df0111::CounterCoverageMappingBuilder8129a199699SDimitry Andric Optional<SourceRange> findGapAreaBetween(const Stmt *AfterStmt,
8139a199699SDimitry Andric const Stmt *BeforeStmt) {
8149a199699SDimitry Andric return findGapAreaBetween(getPreciseTokenLocEnd(getEnd(AfterStmt)),
8159a199699SDimitry Andric getStart(BeforeStmt));
8169a199699SDimitry Andric }
8179a199699SDimitry Andric
8189a199699SDimitry Andric /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
fillGapAreaWithCount__anonc2ccc9df0111::CounterCoverageMappingBuilder8199a199699SDimitry Andric void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
8209a199699SDimitry Andric Counter Count) {
8219a199699SDimitry Andric if (StartLoc == EndLoc)
8229a199699SDimitry Andric return;
8239a199699SDimitry Andric assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
8249a199699SDimitry Andric handleFileExit(StartLoc);
8259a199699SDimitry Andric size_t Index = pushRegion(Count, StartLoc, EndLoc);
8269a199699SDimitry Andric getRegion().setGap(true);
8279a199699SDimitry Andric handleFileExit(EndLoc);
8289a199699SDimitry Andric popRegions(Index);
82933956c43SDimitry Andric }
83039d628a0SDimitry Andric
8314ba319b5SDimitry Andric /// Keep counts of breaks and continues inside loops.
83239d628a0SDimitry Andric struct BreakContinue {
83339d628a0SDimitry Andric Counter BreakCount;
83439d628a0SDimitry Andric Counter ContinueCount;
83539d628a0SDimitry Andric };
83639d628a0SDimitry Andric SmallVector<BreakContinue, 8> BreakContinueStack;
83739d628a0SDimitry Andric
CounterCoverageMappingBuilder__anonc2ccc9df0111::CounterCoverageMappingBuilder83839d628a0SDimitry Andric CounterCoverageMappingBuilder(
83939d628a0SDimitry Andric CoverageMappingModuleGen &CVM,
84039d628a0SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
84139d628a0SDimitry Andric const LangOptions &LangOpts)
8429a199699SDimitry Andric : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
8439a199699SDimitry Andric DeferredRegion(None) {}
84439d628a0SDimitry Andric
8454ba319b5SDimitry Andric /// Write the mapping data to the output stream
write__anonc2ccc9df0111::CounterCoverageMappingBuilder84639d628a0SDimitry Andric void write(llvm::raw_ostream &OS) {
84739d628a0SDimitry Andric llvm::SmallVector<unsigned, 8> VirtualFileMapping;
84833956c43SDimitry Andric gatherFileIDs(VirtualFileMapping);
84944290647SDimitry Andric SourceRegionFilter Filter = emitExpansionRegions();
8509a199699SDimitry Andric assert(!DeferredRegion && "Deferred region never completed");
85144290647SDimitry Andric emitSourceRegions(Filter);
85239d628a0SDimitry Andric gatherSkippedRegions();
85339d628a0SDimitry Andric
85452449daeSDimitry Andric if (MappingRegions.empty())
85552449daeSDimitry Andric return;
85652449daeSDimitry Andric
85733956c43SDimitry Andric CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
85833956c43SDimitry Andric MappingRegions);
85939d628a0SDimitry Andric Writer.write(OS);
86039d628a0SDimitry Andric }
86139d628a0SDimitry Andric
VisitStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder86239d628a0SDimitry Andric void VisitStmt(const Stmt *S) {
863*b5893f02SDimitry Andric if (S->getBeginLoc().isValid())
86433956c43SDimitry Andric extendRegion(S);
8653dac3a9bSDimitry Andric for (const Stmt *Child : S->children())
8663dac3a9bSDimitry Andric if (Child)
8673dac3a9bSDimitry Andric this->Visit(Child);
86833956c43SDimitry Andric handleFileExit(getEnd(S));
86939d628a0SDimitry Andric }
87039d628a0SDimitry Andric
VisitDecl__anonc2ccc9df0111::CounterCoverageMappingBuilder87139d628a0SDimitry Andric void VisitDecl(const Decl *D) {
8729a199699SDimitry Andric assert(!DeferredRegion && "Deferred region never completed");
8739a199699SDimitry Andric
87433956c43SDimitry Andric Stmt *Body = D->getBody();
87552449daeSDimitry Andric
87652449daeSDimitry Andric // Do not propagate region counts into system headers.
87752449daeSDimitry Andric if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
87852449daeSDimitry Andric return;
87952449daeSDimitry Andric
880*b5893f02SDimitry Andric // Do not visit the artificial children nodes of defaulted methods. The
881*b5893f02SDimitry Andric // lexer may not be able to report back precise token end locations for
882*b5893f02SDimitry Andric // these children nodes (llvm.org/PR39822), and moreover users will not be
883*b5893f02SDimitry Andric // able to see coverage for them.
884*b5893f02SDimitry Andric bool Defaulted = false;
885*b5893f02SDimitry Andric if (auto *Method = dyn_cast<CXXMethodDecl>(D))
886*b5893f02SDimitry Andric Defaulted = Method->isDefaulted();
887*b5893f02SDimitry Andric
888*b5893f02SDimitry Andric propagateCounts(getRegionCounter(Body), Body,
889*b5893f02SDimitry Andric /*VisitChildren=*/!Defaulted);
8909a199699SDimitry Andric assert(RegionStack.empty() && "Regions entered but never exited");
8919a199699SDimitry Andric
8924ba319b5SDimitry Andric // Discard the last uncompleted deferred region in a decl, if one exists.
8934ba319b5SDimitry Andric // This prevents lines at the end of a function containing only whitespace
8944ba319b5SDimitry Andric // or closing braces from being marked as uncovered.
8959a199699SDimitry Andric DeferredRegion = None;
89639d628a0SDimitry Andric }
89739d628a0SDimitry Andric
VisitReturnStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder89839d628a0SDimitry Andric void VisitReturnStmt(const ReturnStmt *S) {
89933956c43SDimitry Andric extendRegion(S);
90039d628a0SDimitry Andric if (S->getRetValue())
90139d628a0SDimitry Andric Visit(S->getRetValue());
90233956c43SDimitry Andric terminateRegion(S);
90339d628a0SDimitry Andric }
90439d628a0SDimitry Andric
VisitCXXThrowExpr__anonc2ccc9df0111::CounterCoverageMappingBuilder90533956c43SDimitry Andric void VisitCXXThrowExpr(const CXXThrowExpr *E) {
90633956c43SDimitry Andric extendRegion(E);
90733956c43SDimitry Andric if (E->getSubExpr())
90833956c43SDimitry Andric Visit(E->getSubExpr());
90933956c43SDimitry Andric terminateRegion(E);
91039d628a0SDimitry Andric }
91139d628a0SDimitry Andric
VisitGotoStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder91233956c43SDimitry Andric void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
91333956c43SDimitry Andric
VisitLabelStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder91439d628a0SDimitry Andric void VisitLabelStmt(const LabelStmt *S) {
9159a199699SDimitry Andric Counter LabelCount = getRegionCounter(S);
91633956c43SDimitry Andric SourceLocation Start = getStart(S);
9179a199699SDimitry Andric completeTopLevelDeferredRegion(LabelCount, Start);
9184ba319b5SDimitry Andric completeDeferred(LabelCount, Start);
91933956c43SDimitry Andric // We can't extendRegion here or we risk overlapping with our new region.
92033956c43SDimitry Andric handleFileExit(Start);
9219a199699SDimitry Andric pushRegion(LabelCount, Start);
92239d628a0SDimitry Andric Visit(S->getSubStmt());
92339d628a0SDimitry Andric }
92439d628a0SDimitry Andric
VisitBreakStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder92539d628a0SDimitry Andric void VisitBreakStmt(const BreakStmt *S) {
92639d628a0SDimitry Andric assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
92739d628a0SDimitry Andric BreakContinueStack.back().BreakCount = addCounters(
92833956c43SDimitry Andric BreakContinueStack.back().BreakCount, getRegion().getCounter());
9299a199699SDimitry Andric // FIXME: a break in a switch should terminate regions for all preceding
9309a199699SDimitry Andric // case statements, not just the most recent one.
93133956c43SDimitry Andric terminateRegion(S);
93239d628a0SDimitry Andric }
93339d628a0SDimitry Andric
VisitContinueStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder93439d628a0SDimitry Andric void VisitContinueStmt(const ContinueStmt *S) {
93539d628a0SDimitry Andric assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
93639d628a0SDimitry Andric BreakContinueStack.back().ContinueCount = addCounters(
93733956c43SDimitry Andric BreakContinueStack.back().ContinueCount, getRegion().getCounter());
93833956c43SDimitry Andric terminateRegion(S);
93939d628a0SDimitry Andric }
94039d628a0SDimitry Andric
VisitCallExpr__anonc2ccc9df0111::CounterCoverageMappingBuilder9419a199699SDimitry Andric void VisitCallExpr(const CallExpr *E) {
9429a199699SDimitry Andric VisitStmt(E);
9439a199699SDimitry Andric
9449a199699SDimitry Andric // Terminate the region when we hit a noreturn function.
9459a199699SDimitry Andric // (This is helpful dealing with switch statements.)
9469a199699SDimitry Andric QualType CalleeType = E->getCallee()->getType();
9479a199699SDimitry Andric if (getFunctionExtInfo(*CalleeType).getNoReturn())
9489a199699SDimitry Andric terminateRegion(E);
9499a199699SDimitry Andric }
9509a199699SDimitry Andric
VisitWhileStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder95139d628a0SDimitry Andric void VisitWhileStmt(const WhileStmt *S) {
95233956c43SDimitry Andric extendRegion(S);
95339d628a0SDimitry Andric
95433956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
95533956c43SDimitry Andric Counter BodyCount = getRegionCounter(S);
95633956c43SDimitry Andric
95733956c43SDimitry Andric // Handle the body first so that we can get the backedge count.
95833956c43SDimitry Andric BreakContinueStack.push_back(BreakContinue());
95933956c43SDimitry Andric extendRegion(S->getBody());
96033956c43SDimitry Andric Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
96139d628a0SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
96233956c43SDimitry Andric
96333956c43SDimitry Andric // Go back to handle the condition.
96433956c43SDimitry Andric Counter CondCount =
96533956c43SDimitry Andric addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
96633956c43SDimitry Andric propagateCounts(CondCount, S->getCond());
96733956c43SDimitry Andric adjustForOutOfOrderTraversal(getEnd(S));
96833956c43SDimitry Andric
9699a199699SDimitry Andric // The body count applies to the area immediately after the increment.
9709a199699SDimitry Andric auto Gap = findGapAreaBetween(S->getCond(), S->getBody());
9719a199699SDimitry Andric if (Gap)
9729a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
9739a199699SDimitry Andric
97433956c43SDimitry Andric Counter OutCount =
97533956c43SDimitry Andric addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
97633956c43SDimitry Andric if (OutCount != ParentCount)
97733956c43SDimitry Andric pushRegion(OutCount);
97839d628a0SDimitry Andric }
97939d628a0SDimitry Andric
VisitDoStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder98039d628a0SDimitry Andric void VisitDoStmt(const DoStmt *S) {
98133956c43SDimitry Andric extendRegion(S);
98239d628a0SDimitry Andric
98333956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
98433956c43SDimitry Andric Counter BodyCount = getRegionCounter(S);
98533956c43SDimitry Andric
98633956c43SDimitry Andric BreakContinueStack.push_back(BreakContinue());
98733956c43SDimitry Andric extendRegion(S->getBody());
98833956c43SDimitry Andric Counter BackedgeCount =
98933956c43SDimitry Andric propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
99039d628a0SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
99133956c43SDimitry Andric
99233956c43SDimitry Andric Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
99333956c43SDimitry Andric propagateCounts(CondCount, S->getCond());
99433956c43SDimitry Andric
99533956c43SDimitry Andric Counter OutCount =
99633956c43SDimitry Andric addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
99733956c43SDimitry Andric if (OutCount != ParentCount)
99833956c43SDimitry Andric pushRegion(OutCount);
99939d628a0SDimitry Andric }
100039d628a0SDimitry Andric
VisitForStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder100139d628a0SDimitry Andric void VisitForStmt(const ForStmt *S) {
100233956c43SDimitry Andric extendRegion(S);
100339d628a0SDimitry Andric if (S->getInit())
100439d628a0SDimitry Andric Visit(S->getInit());
100539d628a0SDimitry Andric
100633956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
100733956c43SDimitry Andric Counter BodyCount = getRegionCounter(S);
100833956c43SDimitry Andric
10094ba319b5SDimitry Andric // The loop increment may contain a break or continue.
10104ba319b5SDimitry Andric if (S->getInc())
10114ba319b5SDimitry Andric BreakContinueStack.emplace_back();
10124ba319b5SDimitry Andric
101333956c43SDimitry Andric // Handle the body first so that we can get the backedge count.
10144ba319b5SDimitry Andric BreakContinueStack.emplace_back();
101533956c43SDimitry Andric extendRegion(S->getBody());
101633956c43SDimitry Andric Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
10174ba319b5SDimitry Andric BreakContinue BodyBC = BreakContinueStack.pop_back_val();
101839d628a0SDimitry Andric
101939d628a0SDimitry Andric // The increment is essentially part of the body but it needs to include
102039d628a0SDimitry Andric // the count for all the continue statements.
10214ba319b5SDimitry Andric BreakContinue IncrementBC;
10224ba319b5SDimitry Andric if (const Stmt *Inc = S->getInc()) {
10234ba319b5SDimitry Andric propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
10244ba319b5SDimitry Andric IncrementBC = BreakContinueStack.pop_back_val();
10254ba319b5SDimitry Andric }
102633956c43SDimitry Andric
102733956c43SDimitry Andric // Go back to handle the condition.
10284ba319b5SDimitry Andric Counter CondCount = addCounters(
10294ba319b5SDimitry Andric addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
10304ba319b5SDimitry Andric IncrementBC.ContinueCount);
103133956c43SDimitry Andric if (const Expr *Cond = S->getCond()) {
103233956c43SDimitry Andric propagateCounts(CondCount, Cond);
103333956c43SDimitry Andric adjustForOutOfOrderTraversal(getEnd(S));
103439d628a0SDimitry Andric }
103539d628a0SDimitry Andric
10369a199699SDimitry Andric // The body count applies to the area immediately after the increment.
10379a199699SDimitry Andric auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
10389a199699SDimitry Andric getStart(S->getBody()));
10399a199699SDimitry Andric if (Gap)
10409a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
10419a199699SDimitry Andric
10424ba319b5SDimitry Andric Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
10434ba319b5SDimitry Andric subtractCounters(CondCount, BodyCount));
104433956c43SDimitry Andric if (OutCount != ParentCount)
104533956c43SDimitry Andric pushRegion(OutCount);
104639d628a0SDimitry Andric }
104739d628a0SDimitry Andric
VisitCXXForRangeStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder104839d628a0SDimitry Andric void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
104933956c43SDimitry Andric extendRegion(S);
1050*b5893f02SDimitry Andric if (S->getInit())
1051*b5893f02SDimitry Andric Visit(S->getInit());
105233956c43SDimitry Andric Visit(S->getLoopVarStmt());
105339d628a0SDimitry Andric Visit(S->getRangeStmt());
105433956c43SDimitry Andric
105533956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
105633956c43SDimitry Andric Counter BodyCount = getRegionCounter(S);
105733956c43SDimitry Andric
105839d628a0SDimitry Andric BreakContinueStack.push_back(BreakContinue());
105933956c43SDimitry Andric extendRegion(S->getBody());
106033956c43SDimitry Andric Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
106139d628a0SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
106233956c43SDimitry Andric
10639a199699SDimitry Andric // The body count applies to the area immediately after the range.
10649a199699SDimitry Andric auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
10659a199699SDimitry Andric getStart(S->getBody()));
10669a199699SDimitry Andric if (Gap)
10679a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
10689a199699SDimitry Andric
106933956c43SDimitry Andric Counter LoopCount =
107033956c43SDimitry Andric addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
107133956c43SDimitry Andric Counter OutCount =
107233956c43SDimitry Andric addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
107333956c43SDimitry Andric if (OutCount != ParentCount)
107433956c43SDimitry Andric pushRegion(OutCount);
107539d628a0SDimitry Andric }
107639d628a0SDimitry Andric
VisitObjCForCollectionStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder107739d628a0SDimitry Andric void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
107833956c43SDimitry Andric extendRegion(S);
107939d628a0SDimitry Andric Visit(S->getElement());
108033956c43SDimitry Andric
108133956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
108233956c43SDimitry Andric Counter BodyCount = getRegionCounter(S);
108333956c43SDimitry Andric
108439d628a0SDimitry Andric BreakContinueStack.push_back(BreakContinue());
108533956c43SDimitry Andric extendRegion(S->getBody());
108633956c43SDimitry Andric Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
108739d628a0SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
108833956c43SDimitry Andric
10899a199699SDimitry Andric // The body count applies to the area immediately after the collection.
10909a199699SDimitry Andric auto Gap = findGapAreaBetween(getPreciseTokenLocEnd(S->getRParenLoc()),
10919a199699SDimitry Andric getStart(S->getBody()));
10929a199699SDimitry Andric if (Gap)
10939a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
10949a199699SDimitry Andric
109533956c43SDimitry Andric Counter LoopCount =
109633956c43SDimitry Andric addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
109733956c43SDimitry Andric Counter OutCount =
109833956c43SDimitry Andric addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
109933956c43SDimitry Andric if (OutCount != ParentCount)
110033956c43SDimitry Andric pushRegion(OutCount);
110139d628a0SDimitry Andric }
110239d628a0SDimitry Andric
VisitSwitchStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder110339d628a0SDimitry Andric void VisitSwitchStmt(const SwitchStmt *S) {
110433956c43SDimitry Andric extendRegion(S);
110544290647SDimitry Andric if (S->getInit())
110644290647SDimitry Andric Visit(S->getInit());
110739d628a0SDimitry Andric Visit(S->getCond());
110833956c43SDimitry Andric
110939d628a0SDimitry Andric BreakContinueStack.push_back(BreakContinue());
111033956c43SDimitry Andric
111133956c43SDimitry Andric const Stmt *Body = S->getBody();
111233956c43SDimitry Andric extendRegion(Body);
111333956c43SDimitry Andric if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
111433956c43SDimitry Andric if (!CS->body_empty()) {
11159a199699SDimitry Andric // Make a region for the body of the switch. If the body starts with
11169a199699SDimitry Andric // a case, that case will reuse this region; otherwise, this covers
11179a199699SDimitry Andric // the unreachable code at the beginning of the switch body.
111833956c43SDimitry Andric size_t Index =
11199a199699SDimitry Andric pushRegion(Counter::getZero(), getStart(CS->body_front()));
112033956c43SDimitry Andric for (const auto *Child : CS->children())
112133956c43SDimitry Andric Visit(Child);
11229a199699SDimitry Andric
11239a199699SDimitry Andric // Set the end for the body of the switch, if it isn't already set.
11249a199699SDimitry Andric for (size_t i = RegionStack.size(); i != Index; --i) {
11259a199699SDimitry Andric if (!RegionStack[i - 1].hasEndLoc())
11269a199699SDimitry Andric RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
11279a199699SDimitry Andric }
11289a199699SDimitry Andric
112933956c43SDimitry Andric popRegions(Index);
113039d628a0SDimitry Andric }
113133956c43SDimitry Andric } else
113233956c43SDimitry Andric propagateCounts(Counter::getZero(), Body);
113339d628a0SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
113433956c43SDimitry Andric
113539d628a0SDimitry Andric if (!BreakContinueStack.empty())
113639d628a0SDimitry Andric BreakContinueStack.back().ContinueCount = addCounters(
113739d628a0SDimitry Andric BreakContinueStack.back().ContinueCount, BC.ContinueCount);
113833956c43SDimitry Andric
113933956c43SDimitry Andric Counter ExitCount = getRegionCounter(S);
1140e7145dcbSDimitry Andric SourceLocation ExitLoc = getEnd(S);
114144290647SDimitry Andric pushRegion(ExitCount);
114244290647SDimitry Andric
114344290647SDimitry Andric // Ensure that handleFileExit recognizes when the end location is located
114444290647SDimitry Andric // in a different file.
114544290647SDimitry Andric MostRecentLocation = getStart(S);
1146e7145dcbSDimitry Andric handleFileExit(ExitLoc);
114739d628a0SDimitry Andric }
114839d628a0SDimitry Andric
VisitSwitchCase__anonc2ccc9df0111::CounterCoverageMappingBuilder114933956c43SDimitry Andric void VisitSwitchCase(const SwitchCase *S) {
115033956c43SDimitry Andric extendRegion(S);
115139d628a0SDimitry Andric
115233956c43SDimitry Andric SourceMappingRegion &Parent = getRegion();
115333956c43SDimitry Andric
115433956c43SDimitry Andric Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
115533956c43SDimitry Andric // Reuse the existing region if it starts at our label. This is typical of
115633956c43SDimitry Andric // the first case in a switch.
1157*b5893f02SDimitry Andric if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
115833956c43SDimitry Andric Parent.setCounter(Count);
115933956c43SDimitry Andric else
116033956c43SDimitry Andric pushRegion(Count, getStart(S));
116133956c43SDimitry Andric
11620623d748SDimitry Andric if (const auto *CS = dyn_cast<CaseStmt>(S)) {
116333956c43SDimitry Andric Visit(CS->getLHS());
116433956c43SDimitry Andric if (const Expr *RHS = CS->getRHS())
116533956c43SDimitry Andric Visit(RHS);
116633956c43SDimitry Andric }
116739d628a0SDimitry Andric Visit(S->getSubStmt());
116839d628a0SDimitry Andric }
116939d628a0SDimitry Andric
VisitIfStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder117039d628a0SDimitry Andric void VisitIfStmt(const IfStmt *S) {
117133956c43SDimitry Andric extendRegion(S);
117244290647SDimitry Andric if (S->getInit())
117344290647SDimitry Andric Visit(S->getInit());
117444290647SDimitry Andric
11758f0fd8f6SDimitry Andric // Extend into the condition before we propagate through it below - this is
11768f0fd8f6SDimitry Andric // needed to handle macros that generate the "if" but not the condition.
11778f0fd8f6SDimitry Andric extendRegion(S->getCond());
117839d628a0SDimitry Andric
117933956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
118033956c43SDimitry Andric Counter ThenCount = getRegionCounter(S);
118139d628a0SDimitry Andric
118233956c43SDimitry Andric // Emitting a counter for the condition makes it easier to interpret the
118333956c43SDimitry Andric // counter for the body when looking at the coverage.
118433956c43SDimitry Andric propagateCounts(ParentCount, S->getCond());
118533956c43SDimitry Andric
11869a199699SDimitry Andric // The 'then' count applies to the area immediately after the condition.
11879a199699SDimitry Andric auto Gap = findGapAreaBetween(S->getCond(), S->getThen());
11889a199699SDimitry Andric if (Gap)
11899a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
11909a199699SDimitry Andric
119133956c43SDimitry Andric extendRegion(S->getThen());
119233956c43SDimitry Andric Counter OutCount = propagateCounts(ThenCount, S->getThen());
119333956c43SDimitry Andric
119433956c43SDimitry Andric Counter ElseCount = subtractCounters(ParentCount, ThenCount);
119533956c43SDimitry Andric if (const Stmt *Else = S->getElse()) {
11969a199699SDimitry Andric // The 'else' count applies to the area immediately after the 'then'.
11979a199699SDimitry Andric Gap = findGapAreaBetween(S->getThen(), Else);
11989a199699SDimitry Andric if (Gap)
11999a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
12009a199699SDimitry Andric extendRegion(Else);
120133956c43SDimitry Andric OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
120233956c43SDimitry Andric } else
120333956c43SDimitry Andric OutCount = addCounters(OutCount, ElseCount);
120433956c43SDimitry Andric
120533956c43SDimitry Andric if (OutCount != ParentCount)
120633956c43SDimitry Andric pushRegion(OutCount);
120739d628a0SDimitry Andric }
120839d628a0SDimitry Andric
VisitCXXTryStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder120939d628a0SDimitry Andric void VisitCXXTryStmt(const CXXTryStmt *S) {
121033956c43SDimitry Andric extendRegion(S);
1211e7145dcbSDimitry Andric // Handle macros that generate the "try" but not the rest.
1212e7145dcbSDimitry Andric extendRegion(S->getTryBlock());
1213e7145dcbSDimitry Andric
1214e7145dcbSDimitry Andric Counter ParentCount = getRegion().getCounter();
1215e7145dcbSDimitry Andric propagateCounts(ParentCount, S->getTryBlock());
1216e7145dcbSDimitry Andric
121739d628a0SDimitry Andric for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
121839d628a0SDimitry Andric Visit(S->getHandler(I));
121933956c43SDimitry Andric
122033956c43SDimitry Andric Counter ExitCount = getRegionCounter(S);
122133956c43SDimitry Andric pushRegion(ExitCount);
122239d628a0SDimitry Andric }
122339d628a0SDimitry Andric
VisitCXXCatchStmt__anonc2ccc9df0111::CounterCoverageMappingBuilder122439d628a0SDimitry Andric void VisitCXXCatchStmt(const CXXCatchStmt *S) {
122533956c43SDimitry Andric propagateCounts(getRegionCounter(S), S->getHandlerBlock());
122639d628a0SDimitry Andric }
122739d628a0SDimitry Andric
VisitAbstractConditionalOperator__anonc2ccc9df0111::CounterCoverageMappingBuilder122839d628a0SDimitry Andric void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
122933956c43SDimitry Andric extendRegion(E);
123033956c43SDimitry Andric
123133956c43SDimitry Andric Counter ParentCount = getRegion().getCounter();
123233956c43SDimitry Andric Counter TrueCount = getRegionCounter(E);
123333956c43SDimitry Andric
123439d628a0SDimitry Andric Visit(E->getCond());
123539d628a0SDimitry Andric
123633956c43SDimitry Andric if (!isa<BinaryConditionalOperator>(E)) {
12379a199699SDimitry Andric // The 'then' count applies to the area immediately after the condition.
12389a199699SDimitry Andric auto Gap =
12399a199699SDimitry Andric findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
12409a199699SDimitry Andric if (Gap)
12419a199699SDimitry Andric fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
12429a199699SDimitry Andric
124333956c43SDimitry Andric extendRegion(E->getTrueExpr());
124433956c43SDimitry Andric propagateCounts(TrueCount, E->getTrueExpr());
124533956c43SDimitry Andric }
12469a199699SDimitry Andric
124733956c43SDimitry Andric extendRegion(E->getFalseExpr());
124833956c43SDimitry Andric propagateCounts(subtractCounters(ParentCount, TrueCount),
124933956c43SDimitry Andric E->getFalseExpr());
125039d628a0SDimitry Andric }
125139d628a0SDimitry Andric
VisitBinLAnd__anonc2ccc9df0111::CounterCoverageMappingBuilder125239d628a0SDimitry Andric void VisitBinLAnd(const BinaryOperator *E) {
12539a199699SDimitry Andric extendRegion(E->getLHS());
12549a199699SDimitry Andric propagateCounts(getRegion().getCounter(), E->getLHS());
12559a199699SDimitry Andric handleFileExit(getEnd(E->getLHS()));
125633956c43SDimitry Andric
125733956c43SDimitry Andric extendRegion(E->getRHS());
125833956c43SDimitry Andric propagateCounts(getRegionCounter(E), E->getRHS());
125939d628a0SDimitry Andric }
126039d628a0SDimitry Andric
VisitBinLOr__anonc2ccc9df0111::CounterCoverageMappingBuilder126139d628a0SDimitry Andric void VisitBinLOr(const BinaryOperator *E) {
12629a199699SDimitry Andric extendRegion(E->getLHS());
12639a199699SDimitry Andric propagateCounts(getRegion().getCounter(), E->getLHS());
12649a199699SDimitry Andric handleFileExit(getEnd(E->getLHS()));
126533956c43SDimitry Andric
126633956c43SDimitry Andric extendRegion(E->getRHS());
126733956c43SDimitry Andric propagateCounts(getRegionCounter(E), E->getRHS());
126839d628a0SDimitry Andric }
126939d628a0SDimitry Andric
VisitLambdaExpr__anonc2ccc9df0111::CounterCoverageMappingBuilder127033956c43SDimitry Andric void VisitLambdaExpr(const LambdaExpr *LE) {
127133956c43SDimitry Andric // Lambdas are treated as their own functions for now, so we shouldn't
127233956c43SDimitry Andric // propagate counts into them.
127339d628a0SDimitry Andric }
127439d628a0SDimitry Andric };
127539d628a0SDimitry Andric
getCoverageSection(const CodeGenModule & CGM)127620e90f04SDimitry Andric std::string getCoverageSection(const CodeGenModule &CGM) {
127720e90f04SDimitry Andric return llvm::getInstrProfSectionName(
127820e90f04SDimitry Andric llvm::IPSK_covmap,
127920e90f04SDimitry Andric CGM.getContext().getTargetInfo().getTriple().getObjectFormat());
128039d628a0SDimitry Andric }
128139d628a0SDimitry Andric
normalizeFilename(StringRef Filename)128244290647SDimitry Andric std::string normalizeFilename(StringRef Filename) {
128344290647SDimitry Andric llvm::SmallString<256> Path(Filename);
128444290647SDimitry Andric llvm::sys::fs::make_absolute(Path);
128544290647SDimitry Andric llvm::sys::path::remove_dots(Path, /*remove_dot_dots=*/true);
128644290647SDimitry Andric return Path.str().str();
128744290647SDimitry Andric }
128844290647SDimitry Andric
128944290647SDimitry Andric } // end anonymous namespace
129044290647SDimitry Andric
dump(llvm::raw_ostream & OS,StringRef FunctionName,ArrayRef<CounterExpression> Expressions,ArrayRef<CounterMappingRegion> Regions)129133956c43SDimitry Andric static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
129233956c43SDimitry Andric ArrayRef<CounterExpression> Expressions,
129333956c43SDimitry Andric ArrayRef<CounterMappingRegion> Regions) {
129433956c43SDimitry Andric OS << FunctionName << ":\n";
129533956c43SDimitry Andric CounterMappingContext Ctx(Expressions);
129633956c43SDimitry Andric for (const auto &R : Regions) {
129739d628a0SDimitry Andric OS.indent(2);
129839d628a0SDimitry Andric switch (R.Kind) {
129939d628a0SDimitry Andric case CounterMappingRegion::CodeRegion:
130039d628a0SDimitry Andric break;
130139d628a0SDimitry Andric case CounterMappingRegion::ExpansionRegion:
130239d628a0SDimitry Andric OS << "Expansion,";
130339d628a0SDimitry Andric break;
130439d628a0SDimitry Andric case CounterMappingRegion::SkippedRegion:
130539d628a0SDimitry Andric OS << "Skipped,";
130639d628a0SDimitry Andric break;
13079a199699SDimitry Andric case CounterMappingRegion::GapRegion:
13089a199699SDimitry Andric OS << "Gap,";
13099a199699SDimitry Andric break;
131039d628a0SDimitry Andric }
131139d628a0SDimitry Andric
131233956c43SDimitry Andric OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
131333956c43SDimitry Andric << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
131433956c43SDimitry Andric Ctx.dump(R.Count, OS);
131539d628a0SDimitry Andric if (R.Kind == CounterMappingRegion::ExpansionRegion)
131633956c43SDimitry Andric OS << " (Expanded file = " << R.ExpandedFileID << ")";
131733956c43SDimitry Andric OS << "\n";
131839d628a0SDimitry Andric }
131939d628a0SDimitry Andric }
132039d628a0SDimitry Andric
addFunctionMappingRecord(llvm::GlobalVariable * NamePtr,StringRef NameValue,uint64_t FuncHash,const std::string & CoverageMapping,bool IsUsed)132139d628a0SDimitry Andric void CoverageMappingModuleGen::addFunctionMappingRecord(
1322444ed5c5SDimitry Andric llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1323e7145dcbSDimitry Andric const std::string &CoverageMapping, bool IsUsed) {
132439d628a0SDimitry Andric llvm::LLVMContext &Ctx = CGM.getLLVMContext();
132539d628a0SDimitry Andric if (!FunctionRecordTy) {
13260623d748SDimitry Andric #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
13270623d748SDimitry Andric llvm::Type *FunctionRecordTypes[] = {
13280623d748SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
13290623d748SDimitry Andric };
133039d628a0SDimitry Andric FunctionRecordTy =
13313dac3a9bSDimitry Andric llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
13323dac3a9bSDimitry Andric /*isPacked=*/true);
133339d628a0SDimitry Andric }
133439d628a0SDimitry Andric
13350623d748SDimitry Andric #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
133639d628a0SDimitry Andric llvm::Constant *FunctionRecordVals[] = {
13370623d748SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
13380623d748SDimitry Andric };
133939d628a0SDimitry Andric FunctionRecords.push_back(llvm::ConstantStruct::get(
134039d628a0SDimitry Andric FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
1341e7145dcbSDimitry Andric if (!IsUsed)
1342444ed5c5SDimitry Andric FunctionNames.push_back(
1343444ed5c5SDimitry Andric llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
1344e7145dcbSDimitry Andric CoverageMappings.push_back(CoverageMapping);
134539d628a0SDimitry Andric
134639d628a0SDimitry Andric if (CGM.getCodeGenOpts().DumpCoverageMapping) {
134739d628a0SDimitry Andric // Dump the coverage mapping data for this function by decoding the
134839d628a0SDimitry Andric // encoded data. This allows us to dump the mapping regions which were
134939d628a0SDimitry Andric // also processed by the CoverageMappingWriter which performs
135039d628a0SDimitry Andric // additional minimization operations such as reducing the number of
135139d628a0SDimitry Andric // expressions.
135239d628a0SDimitry Andric std::vector<StringRef> Filenames;
135339d628a0SDimitry Andric std::vector<CounterExpression> Expressions;
135439d628a0SDimitry Andric std::vector<CounterMappingRegion> Regions;
135544290647SDimitry Andric llvm::SmallVector<std::string, 16> FilenameStrs;
135639d628a0SDimitry Andric llvm::SmallVector<StringRef, 16> FilenameRefs;
135744290647SDimitry Andric FilenameStrs.resize(FileEntries.size());
135839d628a0SDimitry Andric FilenameRefs.resize(FileEntries.size());
135944290647SDimitry Andric for (const auto &Entry : FileEntries) {
136044290647SDimitry Andric auto I = Entry.second;
136144290647SDimitry Andric FilenameStrs[I] = normalizeFilename(Entry.first->getName());
136244290647SDimitry Andric FilenameRefs[I] = FilenameStrs[I];
136344290647SDimitry Andric }
136433956c43SDimitry Andric RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
136533956c43SDimitry Andric Expressions, Regions);
136633956c43SDimitry Andric if (Reader.read())
136739d628a0SDimitry Andric return;
13680623d748SDimitry Andric dump(llvm::outs(), NameValue, Expressions, Regions);
136939d628a0SDimitry Andric }
137039d628a0SDimitry Andric }
137139d628a0SDimitry Andric
emit()137239d628a0SDimitry Andric void CoverageMappingModuleGen::emit() {
137339d628a0SDimitry Andric if (FunctionRecords.empty())
137439d628a0SDimitry Andric return;
137539d628a0SDimitry Andric llvm::LLVMContext &Ctx = CGM.getLLVMContext();
137639d628a0SDimitry Andric auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
137739d628a0SDimitry Andric
137839d628a0SDimitry Andric // Create the filenames and merge them with coverage mappings
137939d628a0SDimitry Andric llvm::SmallVector<std::string, 16> FilenameStrs;
138039d628a0SDimitry Andric llvm::SmallVector<StringRef, 16> FilenameRefs;
138139d628a0SDimitry Andric FilenameStrs.resize(FileEntries.size());
138239d628a0SDimitry Andric FilenameRefs.resize(FileEntries.size());
138339d628a0SDimitry Andric for (const auto &Entry : FileEntries) {
138439d628a0SDimitry Andric auto I = Entry.second;
138544290647SDimitry Andric FilenameStrs[I] = normalizeFilename(Entry.first->getName());
138639d628a0SDimitry Andric FilenameRefs[I] = FilenameStrs[I];
138739d628a0SDimitry Andric }
138839d628a0SDimitry Andric
138939d628a0SDimitry Andric std::string FilenamesAndCoverageMappings;
139039d628a0SDimitry Andric llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
139139d628a0SDimitry Andric CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
1392e7145dcbSDimitry Andric std::string RawCoverageMappings =
1393e7145dcbSDimitry Andric llvm::join(CoverageMappings.begin(), CoverageMappings.end(), "");
1394e7145dcbSDimitry Andric OS << RawCoverageMappings;
1395e7145dcbSDimitry Andric size_t CoverageMappingSize = RawCoverageMappings.size();
139639d628a0SDimitry Andric size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
139739d628a0SDimitry Andric // Append extra zeroes if necessary to ensure that the size of the filenames
139839d628a0SDimitry Andric // and coverage mappings is a multiple of 8.
139939d628a0SDimitry Andric if (size_t Rem = OS.str().size() % 8) {
140039d628a0SDimitry Andric CoverageMappingSize += 8 - Rem;
14014ba319b5SDimitry Andric OS.write_zeros(8 - Rem);
140239d628a0SDimitry Andric }
140339d628a0SDimitry Andric auto *FilenamesAndMappingsVal =
140439d628a0SDimitry Andric llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
140539d628a0SDimitry Andric
140639d628a0SDimitry Andric // Create the deferred function records array
140739d628a0SDimitry Andric auto RecordsTy =
140839d628a0SDimitry Andric llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
140939d628a0SDimitry Andric auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
141039d628a0SDimitry Andric
1411ea942507SDimitry Andric llvm::Type *CovDataHeaderTypes[] = {
1412ea942507SDimitry Andric #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
1413ea942507SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1414ea942507SDimitry Andric };
1415ea942507SDimitry Andric auto CovDataHeaderTy =
1416ea942507SDimitry Andric llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
1417ea942507SDimitry Andric llvm::Constant *CovDataHeaderVals[] = {
1418ea942507SDimitry Andric #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
1419ea942507SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
1420ea942507SDimitry Andric };
1421ea942507SDimitry Andric auto CovDataHeaderVal = llvm::ConstantStruct::get(
1422ea942507SDimitry Andric CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
1423ea942507SDimitry Andric
142439d628a0SDimitry Andric // Create the coverage data record
1425ea942507SDimitry Andric llvm::Type *CovDataTypes[] = {CovDataHeaderTy, RecordsTy,
1426ea942507SDimitry Andric FilenamesAndMappingsVal->getType()};
142739d628a0SDimitry Andric auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1428ea942507SDimitry Andric llvm::Constant *TUDataVals[] = {CovDataHeaderVal, RecordsVal,
1429ea942507SDimitry Andric FilenamesAndMappingsVal};
143039d628a0SDimitry Andric auto CovDataVal =
143139d628a0SDimitry Andric llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
1432ea942507SDimitry Andric auto CovData = new llvm::GlobalVariable(
1433ea942507SDimitry Andric CGM.getModule(), CovDataTy, true, llvm::GlobalValue::InternalLinkage,
1434ea942507SDimitry Andric CovDataVal, llvm::getCoverageMappingVarName());
143539d628a0SDimitry Andric
143639d628a0SDimitry Andric CovData->setSection(getCoverageSection(CGM));
143739d628a0SDimitry Andric CovData->setAlignment(8);
143839d628a0SDimitry Andric
143939d628a0SDimitry Andric // Make sure the data doesn't get deleted.
144039d628a0SDimitry Andric CGM.addUsedGlobal(CovData);
1441444ed5c5SDimitry Andric // Create the deferred function records array
1442444ed5c5SDimitry Andric if (!FunctionNames.empty()) {
1443444ed5c5SDimitry Andric auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
1444444ed5c5SDimitry Andric FunctionNames.size());
1445444ed5c5SDimitry Andric auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
1446444ed5c5SDimitry Andric // This variable will *NOT* be emitted to the object file. It is used
1447444ed5c5SDimitry Andric // to pass the list of names referenced to codegen.
1448444ed5c5SDimitry Andric new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
1449444ed5c5SDimitry Andric llvm::GlobalValue::InternalLinkage, NamesArrVal,
1450e7145dcbSDimitry Andric llvm::getCoverageUnusedNamesVarName());
1451444ed5c5SDimitry Andric }
145239d628a0SDimitry Andric }
145339d628a0SDimitry Andric
getFileID(const FileEntry * File)145439d628a0SDimitry Andric unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
145539d628a0SDimitry Andric auto It = FileEntries.find(File);
145639d628a0SDimitry Andric if (It != FileEntries.end())
145739d628a0SDimitry Andric return It->second;
145839d628a0SDimitry Andric unsigned FileID = FileEntries.size();
145939d628a0SDimitry Andric FileEntries.insert(std::make_pair(File, FileID));
146039d628a0SDimitry Andric return FileID;
146139d628a0SDimitry Andric }
146239d628a0SDimitry Andric
emitCounterMapping(const Decl * D,llvm::raw_ostream & OS)146339d628a0SDimitry Andric void CoverageMappingGen::emitCounterMapping(const Decl *D,
146439d628a0SDimitry Andric llvm::raw_ostream &OS) {
146539d628a0SDimitry Andric assert(CounterMap);
146639d628a0SDimitry Andric CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts);
146739d628a0SDimitry Andric Walker.VisitDecl(D);
146839d628a0SDimitry Andric Walker.write(OS);
146939d628a0SDimitry Andric }
147039d628a0SDimitry Andric
emitEmptyMapping(const Decl * D,llvm::raw_ostream & OS)147139d628a0SDimitry Andric void CoverageMappingGen::emitEmptyMapping(const Decl *D,
147239d628a0SDimitry Andric llvm::raw_ostream &OS) {
147339d628a0SDimitry Andric EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
147439d628a0SDimitry Andric Walker.VisitDecl(D);
147539d628a0SDimitry Andric Walker.write(OS);
147639d628a0SDimitry Andric }
1477