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