xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/CodeGen/CoverageMappingGen.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // Instrumentation-based code coverage mapping generator
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "CoverageMappingGen.h"
147330f729Sjoerg #include "CodeGenFunction.h"
157330f729Sjoerg #include "clang/AST/StmtVisitor.h"
16*e038c9c4Sjoerg #include "clang/Basic/Diagnostic.h"
17*e038c9c4Sjoerg #include "clang/Basic/FileManager.h"
18*e038c9c4Sjoerg #include "clang/Frontend/FrontendDiagnostic.h"
197330f729Sjoerg #include "clang/Lex/Lexer.h"
20*e038c9c4Sjoerg #include "llvm/ADT/Optional.h"
217330f729Sjoerg #include "llvm/ADT/SmallSet.h"
227330f729Sjoerg #include "llvm/ADT/StringExtras.h"
237330f729Sjoerg #include "llvm/ProfileData/Coverage/CoverageMapping.h"
247330f729Sjoerg #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
257330f729Sjoerg #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
267330f729Sjoerg #include "llvm/ProfileData/InstrProfReader.h"
277330f729Sjoerg #include "llvm/Support/FileSystem.h"
287330f729Sjoerg #include "llvm/Support/Path.h"
297330f729Sjoerg 
30*e038c9c4Sjoerg // This selects the coverage mapping format defined when `InstrProfData.inc`
31*e038c9c4Sjoerg // is textually included.
32*e038c9c4Sjoerg #define COVMAP_V3
33*e038c9c4Sjoerg 
34*e038c9c4Sjoerg static llvm::cl::opt<bool> EmptyLineCommentCoverage(
35*e038c9c4Sjoerg     "emptyline-comment-coverage",
36*e038c9c4Sjoerg     llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only "
37*e038c9c4Sjoerg                    "disable it on test)"),
38*e038c9c4Sjoerg     llvm::cl::init(true), llvm::cl::Hidden);
39*e038c9c4Sjoerg 
407330f729Sjoerg using namespace clang;
417330f729Sjoerg using namespace CodeGen;
427330f729Sjoerg using namespace llvm::coverage;
437330f729Sjoerg 
44*e038c9c4Sjoerg CoverageSourceInfo *
setUpCoverageCallbacks(Preprocessor & PP)45*e038c9c4Sjoerg CoverageMappingModuleGen::setUpCoverageCallbacks(Preprocessor &PP) {
46*e038c9c4Sjoerg   CoverageSourceInfo *CoverageInfo =
47*e038c9c4Sjoerg       new CoverageSourceInfo(PP.getSourceManager());
48*e038c9c4Sjoerg   PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(CoverageInfo));
49*e038c9c4Sjoerg   if (EmptyLineCommentCoverage) {
50*e038c9c4Sjoerg     PP.addCommentHandler(CoverageInfo);
51*e038c9c4Sjoerg     PP.setEmptylineHandler(CoverageInfo);
52*e038c9c4Sjoerg     PP.setPreprocessToken(true);
53*e038c9c4Sjoerg     PP.setTokenWatcher([CoverageInfo](clang::Token Tok) {
54*e038c9c4Sjoerg       // Update previous token location.
55*e038c9c4Sjoerg       CoverageInfo->PrevTokLoc = Tok.getLocation();
56*e038c9c4Sjoerg       if (Tok.getKind() != clang::tok::eod)
57*e038c9c4Sjoerg         CoverageInfo->updateNextTokLoc(Tok.getLocation());
58*e038c9c4Sjoerg     });
59*e038c9c4Sjoerg   }
60*e038c9c4Sjoerg   return CoverageInfo;
61*e038c9c4Sjoerg }
62*e038c9c4Sjoerg 
AddSkippedRange(SourceRange Range)63*e038c9c4Sjoerg void CoverageSourceInfo::AddSkippedRange(SourceRange Range) {
64*e038c9c4Sjoerg   if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
65*e038c9c4Sjoerg       PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
66*e038c9c4Sjoerg       SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
67*e038c9c4Sjoerg                                     Range.getBegin()))
68*e038c9c4Sjoerg     SkippedRanges.back().Range.setEnd(Range.getEnd());
69*e038c9c4Sjoerg   else
70*e038c9c4Sjoerg     SkippedRanges.push_back({Range, PrevTokLoc});
71*e038c9c4Sjoerg }
72*e038c9c4Sjoerg 
SourceRangeSkipped(SourceRange Range,SourceLocation)737330f729Sjoerg void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
74*e038c9c4Sjoerg   AddSkippedRange(Range);
75*e038c9c4Sjoerg }
76*e038c9c4Sjoerg 
HandleEmptyline(SourceRange Range)77*e038c9c4Sjoerg void CoverageSourceInfo::HandleEmptyline(SourceRange Range) {
78*e038c9c4Sjoerg   AddSkippedRange(Range);
79*e038c9c4Sjoerg }
80*e038c9c4Sjoerg 
HandleComment(Preprocessor & PP,SourceRange Range)81*e038c9c4Sjoerg bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) {
82*e038c9c4Sjoerg   AddSkippedRange(Range);
83*e038c9c4Sjoerg   return false;
84*e038c9c4Sjoerg }
85*e038c9c4Sjoerg 
updateNextTokLoc(SourceLocation Loc)86*e038c9c4Sjoerg void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) {
87*e038c9c4Sjoerg   if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid())
88*e038c9c4Sjoerg     SkippedRanges.back().NextTokLoc = Loc;
897330f729Sjoerg }
907330f729Sjoerg 
917330f729Sjoerg namespace {
927330f729Sjoerg 
937330f729Sjoerg /// A region of source code that can be mapped to a counter.
947330f729Sjoerg class SourceMappingRegion {
95*e038c9c4Sjoerg   /// Primary Counter that is also used for Branch Regions for "True" branches.
967330f729Sjoerg   Counter Count;
977330f729Sjoerg 
98*e038c9c4Sjoerg   /// Secondary Counter used for Branch Regions for "False" branches.
99*e038c9c4Sjoerg   Optional<Counter> FalseCount;
100*e038c9c4Sjoerg 
1017330f729Sjoerg   /// The region's starting location.
1027330f729Sjoerg   Optional<SourceLocation> LocStart;
1037330f729Sjoerg 
1047330f729Sjoerg   /// The region's ending location.
1057330f729Sjoerg   Optional<SourceLocation> LocEnd;
1067330f729Sjoerg 
1077330f729Sjoerg   /// Whether this region is a gap region. The count from a gap region is set
1087330f729Sjoerg   /// as the line execution count if there are no other regions on the line.
1097330f729Sjoerg   bool GapRegion;
1107330f729Sjoerg 
1117330f729Sjoerg public:
SourceMappingRegion(Counter Count,Optional<SourceLocation> LocStart,Optional<SourceLocation> LocEnd,bool GapRegion=false)1127330f729Sjoerg   SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
113*e038c9c4Sjoerg                       Optional<SourceLocation> LocEnd, bool GapRegion = false)
114*e038c9c4Sjoerg       : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {
115*e038c9c4Sjoerg   }
116*e038c9c4Sjoerg 
SourceMappingRegion(Counter Count,Optional<Counter> FalseCount,Optional<SourceLocation> LocStart,Optional<SourceLocation> LocEnd,bool GapRegion=false)117*e038c9c4Sjoerg   SourceMappingRegion(Counter Count, Optional<Counter> FalseCount,
118*e038c9c4Sjoerg                       Optional<SourceLocation> LocStart,
119*e038c9c4Sjoerg                       Optional<SourceLocation> LocEnd, bool GapRegion = false)
120*e038c9c4Sjoerg       : Count(Count), FalseCount(FalseCount), LocStart(LocStart),
121*e038c9c4Sjoerg         LocEnd(LocEnd), GapRegion(GapRegion) {}
1227330f729Sjoerg 
getCounter() const1237330f729Sjoerg   const Counter &getCounter() const { return Count; }
1247330f729Sjoerg 
getFalseCounter() const125*e038c9c4Sjoerg   const Counter &getFalseCounter() const {
126*e038c9c4Sjoerg     assert(FalseCount && "Region has no alternate counter");
127*e038c9c4Sjoerg     return *FalseCount;
128*e038c9c4Sjoerg   }
129*e038c9c4Sjoerg 
setCounter(Counter C)1307330f729Sjoerg   void setCounter(Counter C) { Count = C; }
1317330f729Sjoerg 
hasStartLoc() const1327330f729Sjoerg   bool hasStartLoc() const { return LocStart.hasValue(); }
1337330f729Sjoerg 
setStartLoc(SourceLocation Loc)1347330f729Sjoerg   void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
1357330f729Sjoerg 
getBeginLoc() const1367330f729Sjoerg   SourceLocation getBeginLoc() const {
1377330f729Sjoerg     assert(LocStart && "Region has no start location");
1387330f729Sjoerg     return *LocStart;
1397330f729Sjoerg   }
1407330f729Sjoerg 
hasEndLoc() const1417330f729Sjoerg   bool hasEndLoc() const { return LocEnd.hasValue(); }
1427330f729Sjoerg 
setEndLoc(SourceLocation Loc)1437330f729Sjoerg   void setEndLoc(SourceLocation Loc) {
1447330f729Sjoerg     assert(Loc.isValid() && "Setting an invalid end location");
1457330f729Sjoerg     LocEnd = Loc;
1467330f729Sjoerg   }
1477330f729Sjoerg 
getEndLoc() const1487330f729Sjoerg   SourceLocation getEndLoc() const {
1497330f729Sjoerg     assert(LocEnd && "Region has no end location");
1507330f729Sjoerg     return *LocEnd;
1517330f729Sjoerg   }
1527330f729Sjoerg 
isGap() const1537330f729Sjoerg   bool isGap() const { return GapRegion; }
1547330f729Sjoerg 
setGap(bool Gap)1557330f729Sjoerg   void setGap(bool Gap) { GapRegion = Gap; }
156*e038c9c4Sjoerg 
isBranch() const157*e038c9c4Sjoerg   bool isBranch() const { return FalseCount.hasValue(); }
1587330f729Sjoerg };
1597330f729Sjoerg 
1607330f729Sjoerg /// Spelling locations for the start and end of a source region.
1617330f729Sjoerg struct SpellingRegion {
1627330f729Sjoerg   /// The line where the region starts.
1637330f729Sjoerg   unsigned LineStart;
1647330f729Sjoerg 
1657330f729Sjoerg   /// The column where the region starts.
1667330f729Sjoerg   unsigned ColumnStart;
1677330f729Sjoerg 
1687330f729Sjoerg   /// The line where the region ends.
1697330f729Sjoerg   unsigned LineEnd;
1707330f729Sjoerg 
1717330f729Sjoerg   /// The column where the region ends.
1727330f729Sjoerg   unsigned ColumnEnd;
1737330f729Sjoerg 
SpellingRegion__anon8c3eb65b0211::SpellingRegion1747330f729Sjoerg   SpellingRegion(SourceManager &SM, SourceLocation LocStart,
1757330f729Sjoerg                  SourceLocation LocEnd) {
1767330f729Sjoerg     LineStart = SM.getSpellingLineNumber(LocStart);
1777330f729Sjoerg     ColumnStart = SM.getSpellingColumnNumber(LocStart);
1787330f729Sjoerg     LineEnd = SM.getSpellingLineNumber(LocEnd);
1797330f729Sjoerg     ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
1807330f729Sjoerg   }
1817330f729Sjoerg 
SpellingRegion__anon8c3eb65b0211::SpellingRegion1827330f729Sjoerg   SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
1837330f729Sjoerg       : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
1847330f729Sjoerg 
1857330f729Sjoerg   /// Check if the start and end locations appear in source order, i.e
1867330f729Sjoerg   /// top->bottom, left->right.
isInSourceOrder__anon8c3eb65b0211::SpellingRegion1877330f729Sjoerg   bool isInSourceOrder() const {
1887330f729Sjoerg     return (LineStart < LineEnd) ||
1897330f729Sjoerg            (LineStart == LineEnd && ColumnStart <= ColumnEnd);
1907330f729Sjoerg   }
1917330f729Sjoerg };
1927330f729Sjoerg 
1937330f729Sjoerg /// Provides the common functionality for the different
1947330f729Sjoerg /// coverage mapping region builders.
1957330f729Sjoerg class CoverageMappingBuilder {
1967330f729Sjoerg public:
1977330f729Sjoerg   CoverageMappingModuleGen &CVM;
1987330f729Sjoerg   SourceManager &SM;
1997330f729Sjoerg   const LangOptions &LangOpts;
2007330f729Sjoerg 
2017330f729Sjoerg private:
2027330f729Sjoerg   /// Map of clang's FileIDs to IDs used for coverage mapping.
2037330f729Sjoerg   llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
2047330f729Sjoerg       FileIDMapping;
2057330f729Sjoerg 
2067330f729Sjoerg public:
2077330f729Sjoerg   /// The coverage mapping regions for this function
2087330f729Sjoerg   llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
2097330f729Sjoerg   /// The source mapping regions for this function.
2107330f729Sjoerg   std::vector<SourceMappingRegion> SourceRegions;
2117330f729Sjoerg 
2127330f729Sjoerg   /// A set of regions which can be used as a filter.
2137330f729Sjoerg   ///
2147330f729Sjoerg   /// It is produced by emitExpansionRegions() and is used in
2157330f729Sjoerg   /// emitSourceRegions() to suppress producing code regions if
2167330f729Sjoerg   /// the same area is covered by expansion regions.
2177330f729Sjoerg   typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
2187330f729Sjoerg       SourceRegionFilter;
2197330f729Sjoerg 
CoverageMappingBuilder(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)2207330f729Sjoerg   CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
2217330f729Sjoerg                          const LangOptions &LangOpts)
2227330f729Sjoerg       : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
2237330f729Sjoerg 
2247330f729Sjoerg   /// Return the precise end location for the given token.
getPreciseTokenLocEnd(SourceLocation Loc)2257330f729Sjoerg   SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
2267330f729Sjoerg     // We avoid getLocForEndOfToken here, because it doesn't do what we want for
2277330f729Sjoerg     // macro locations, which we just treat as expanded files.
2287330f729Sjoerg     unsigned TokLen =
2297330f729Sjoerg         Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
2307330f729Sjoerg     return Loc.getLocWithOffset(TokLen);
2317330f729Sjoerg   }
2327330f729Sjoerg 
2337330f729Sjoerg   /// Return the start location of an included file or expanded macro.
getStartOfFileOrMacro(SourceLocation Loc)2347330f729Sjoerg   SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
2357330f729Sjoerg     if (Loc.isMacroID())
2367330f729Sjoerg       return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
2377330f729Sjoerg     return SM.getLocForStartOfFile(SM.getFileID(Loc));
2387330f729Sjoerg   }
2397330f729Sjoerg 
2407330f729Sjoerg   /// Return the end location of an included file or expanded macro.
getEndOfFileOrMacro(SourceLocation Loc)2417330f729Sjoerg   SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
2427330f729Sjoerg     if (Loc.isMacroID())
2437330f729Sjoerg       return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
2447330f729Sjoerg                                   SM.getFileOffset(Loc));
2457330f729Sjoerg     return SM.getLocForEndOfFile(SM.getFileID(Loc));
2467330f729Sjoerg   }
2477330f729Sjoerg 
2487330f729Sjoerg   /// Find out where the current file is included or macro is expanded.
getIncludeOrExpansionLoc(SourceLocation Loc)2497330f729Sjoerg   SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
2507330f729Sjoerg     return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
2517330f729Sjoerg                            : SM.getIncludeLoc(SM.getFileID(Loc));
2527330f729Sjoerg   }
2537330f729Sjoerg 
2547330f729Sjoerg   /// Return true if \c Loc is a location in a built-in macro.
isInBuiltin(SourceLocation Loc)2557330f729Sjoerg   bool isInBuiltin(SourceLocation Loc) {
2567330f729Sjoerg     return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
2577330f729Sjoerg   }
2587330f729Sjoerg 
2597330f729Sjoerg   /// Check whether \c Loc is included or expanded from \c Parent.
isNestedIn(SourceLocation Loc,FileID Parent)2607330f729Sjoerg   bool isNestedIn(SourceLocation Loc, FileID Parent) {
2617330f729Sjoerg     do {
2627330f729Sjoerg       Loc = getIncludeOrExpansionLoc(Loc);
2637330f729Sjoerg       if (Loc.isInvalid())
2647330f729Sjoerg         return false;
2657330f729Sjoerg     } while (!SM.isInFileID(Loc, Parent));
2667330f729Sjoerg     return true;
2677330f729Sjoerg   }
2687330f729Sjoerg 
2697330f729Sjoerg   /// Get the start of \c S ignoring macro arguments and builtin macros.
getStart(const Stmt * S)2707330f729Sjoerg   SourceLocation getStart(const Stmt *S) {
2717330f729Sjoerg     SourceLocation Loc = S->getBeginLoc();
2727330f729Sjoerg     while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
2737330f729Sjoerg       Loc = SM.getImmediateExpansionRange(Loc).getBegin();
2747330f729Sjoerg     return Loc;
2757330f729Sjoerg   }
2767330f729Sjoerg 
2777330f729Sjoerg   /// Get the end of \c S ignoring macro arguments and builtin macros.
getEnd(const Stmt * S)2787330f729Sjoerg   SourceLocation getEnd(const Stmt *S) {
2797330f729Sjoerg     SourceLocation Loc = S->getEndLoc();
2807330f729Sjoerg     while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
2817330f729Sjoerg       Loc = SM.getImmediateExpansionRange(Loc).getBegin();
2827330f729Sjoerg     return getPreciseTokenLocEnd(Loc);
2837330f729Sjoerg   }
2847330f729Sjoerg 
2857330f729Sjoerg   /// Find the set of files we have regions for and assign IDs
2867330f729Sjoerg   ///
2877330f729Sjoerg   /// Fills \c Mapping with the virtual file mapping needed to write out
2887330f729Sjoerg   /// coverage and collects the necessary file information to emit source and
2897330f729Sjoerg   /// expansion regions.
gatherFileIDs(SmallVectorImpl<unsigned> & Mapping)2907330f729Sjoerg   void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
2917330f729Sjoerg     FileIDMapping.clear();
2927330f729Sjoerg 
2937330f729Sjoerg     llvm::SmallSet<FileID, 8> Visited;
2947330f729Sjoerg     SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
2957330f729Sjoerg     for (const auto &Region : SourceRegions) {
2967330f729Sjoerg       SourceLocation Loc = Region.getBeginLoc();
2977330f729Sjoerg       FileID File = SM.getFileID(Loc);
2987330f729Sjoerg       if (!Visited.insert(File).second)
2997330f729Sjoerg         continue;
3007330f729Sjoerg 
3017330f729Sjoerg       // Do not map FileID's associated with system headers.
3027330f729Sjoerg       if (SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
3037330f729Sjoerg         continue;
3047330f729Sjoerg 
3057330f729Sjoerg       unsigned Depth = 0;
3067330f729Sjoerg       for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
3077330f729Sjoerg            Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
3087330f729Sjoerg         ++Depth;
3097330f729Sjoerg       FileLocs.push_back(std::make_pair(Loc, Depth));
3107330f729Sjoerg     }
3117330f729Sjoerg     llvm::stable_sort(FileLocs, llvm::less_second());
3127330f729Sjoerg 
3137330f729Sjoerg     for (const auto &FL : FileLocs) {
3147330f729Sjoerg       SourceLocation Loc = FL.first;
3157330f729Sjoerg       FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
3167330f729Sjoerg       auto Entry = SM.getFileEntryForID(SpellingFile);
3177330f729Sjoerg       if (!Entry)
3187330f729Sjoerg         continue;
3197330f729Sjoerg 
3207330f729Sjoerg       FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
3217330f729Sjoerg       Mapping.push_back(CVM.getFileID(Entry));
3227330f729Sjoerg     }
3237330f729Sjoerg   }
3247330f729Sjoerg 
3257330f729Sjoerg   /// Get the coverage mapping file ID for \c Loc.
3267330f729Sjoerg   ///
3277330f729Sjoerg   /// If such file id doesn't exist, return None.
getCoverageFileID(SourceLocation Loc)3287330f729Sjoerg   Optional<unsigned> getCoverageFileID(SourceLocation Loc) {
3297330f729Sjoerg     auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
3307330f729Sjoerg     if (Mapping != FileIDMapping.end())
3317330f729Sjoerg       return Mapping->second.first;
3327330f729Sjoerg     return None;
3337330f729Sjoerg   }
3347330f729Sjoerg 
335*e038c9c4Sjoerg   /// This shrinks the skipped range if it spans a line that contains a
336*e038c9c4Sjoerg   /// non-comment token. If shrinking the skipped range would make it empty,
337*e038c9c4Sjoerg   /// this returns None.
adjustSkippedRange(SourceManager & SM,SourceLocation LocStart,SourceLocation LocEnd,SourceLocation PrevTokLoc,SourceLocation NextTokLoc)338*e038c9c4Sjoerg   Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
339*e038c9c4Sjoerg                                               SourceLocation LocStart,
340*e038c9c4Sjoerg                                               SourceLocation LocEnd,
341*e038c9c4Sjoerg                                               SourceLocation PrevTokLoc,
342*e038c9c4Sjoerg                                               SourceLocation NextTokLoc) {
343*e038c9c4Sjoerg     SpellingRegion SR{SM, LocStart, LocEnd};
344*e038c9c4Sjoerg     SR.ColumnStart = 1;
345*e038c9c4Sjoerg     if (PrevTokLoc.isValid() && SM.isWrittenInSameFile(LocStart, PrevTokLoc) &&
346*e038c9c4Sjoerg         SR.LineStart == SM.getSpellingLineNumber(PrevTokLoc))
347*e038c9c4Sjoerg       SR.LineStart++;
348*e038c9c4Sjoerg     if (NextTokLoc.isValid() && SM.isWrittenInSameFile(LocEnd, NextTokLoc) &&
349*e038c9c4Sjoerg         SR.LineEnd == SM.getSpellingLineNumber(NextTokLoc)) {
350*e038c9c4Sjoerg       SR.LineEnd--;
351*e038c9c4Sjoerg       SR.ColumnEnd++;
352*e038c9c4Sjoerg     }
353*e038c9c4Sjoerg     if (SR.isInSourceOrder())
354*e038c9c4Sjoerg       return SR;
355*e038c9c4Sjoerg     return None;
356*e038c9c4Sjoerg   }
357*e038c9c4Sjoerg 
3587330f729Sjoerg   /// Gather all the regions that were skipped by the preprocessor
359*e038c9c4Sjoerg   /// using the constructs like #if or comments.
gatherSkippedRegions()3607330f729Sjoerg   void gatherSkippedRegions() {
3617330f729Sjoerg     /// An array of the minimum lineStarts and the maximum lineEnds
3627330f729Sjoerg     /// for mapping regions from the appropriate source files.
3637330f729Sjoerg     llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
3647330f729Sjoerg     FileLineRanges.resize(
3657330f729Sjoerg         FileIDMapping.size(),
3667330f729Sjoerg         std::make_pair(std::numeric_limits<unsigned>::max(), 0));
3677330f729Sjoerg     for (const auto &R : MappingRegions) {
3687330f729Sjoerg       FileLineRanges[R.FileID].first =
3697330f729Sjoerg           std::min(FileLineRanges[R.FileID].first, R.LineStart);
3707330f729Sjoerg       FileLineRanges[R.FileID].second =
3717330f729Sjoerg           std::max(FileLineRanges[R.FileID].second, R.LineEnd);
3727330f729Sjoerg     }
3737330f729Sjoerg 
3747330f729Sjoerg     auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
375*e038c9c4Sjoerg     for (auto &I : SkippedRanges) {
376*e038c9c4Sjoerg       SourceRange Range = I.Range;
377*e038c9c4Sjoerg       auto LocStart = Range.getBegin();
378*e038c9c4Sjoerg       auto LocEnd = Range.getEnd();
3797330f729Sjoerg       assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
3807330f729Sjoerg              "region spans multiple files");
3817330f729Sjoerg 
3827330f729Sjoerg       auto CovFileID = getCoverageFileID(LocStart);
3837330f729Sjoerg       if (!CovFileID)
3847330f729Sjoerg         continue;
385*e038c9c4Sjoerg       Optional<SpellingRegion> SR =
386*e038c9c4Sjoerg           adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, I.NextTokLoc);
387*e038c9c4Sjoerg       if (!SR.hasValue())
388*e038c9c4Sjoerg         continue;
3897330f729Sjoerg       auto Region = CounterMappingRegion::makeSkipped(
390*e038c9c4Sjoerg           *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd,
391*e038c9c4Sjoerg           SR->ColumnEnd);
3927330f729Sjoerg       // Make sure that we only collect the regions that are inside
3937330f729Sjoerg       // the source code of this function.
3947330f729Sjoerg       if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
3957330f729Sjoerg           Region.LineEnd <= FileLineRanges[*CovFileID].second)
3967330f729Sjoerg         MappingRegions.push_back(Region);
3977330f729Sjoerg     }
3987330f729Sjoerg   }
3997330f729Sjoerg 
4007330f729Sjoerg   /// Generate the coverage counter mapping regions from collected
4017330f729Sjoerg   /// source regions.
emitSourceRegions(const SourceRegionFilter & Filter)4027330f729Sjoerg   void emitSourceRegions(const SourceRegionFilter &Filter) {
4037330f729Sjoerg     for (const auto &Region : SourceRegions) {
4047330f729Sjoerg       assert(Region.hasEndLoc() && "incomplete region");
4057330f729Sjoerg 
4067330f729Sjoerg       SourceLocation LocStart = Region.getBeginLoc();
4077330f729Sjoerg       assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
4087330f729Sjoerg 
4097330f729Sjoerg       // Ignore regions from system headers.
4107330f729Sjoerg       if (SM.isInSystemHeader(SM.getSpellingLoc(LocStart)))
4117330f729Sjoerg         continue;
4127330f729Sjoerg 
4137330f729Sjoerg       auto CovFileID = getCoverageFileID(LocStart);
4147330f729Sjoerg       // Ignore regions that don't have a file, such as builtin macros.
4157330f729Sjoerg       if (!CovFileID)
4167330f729Sjoerg         continue;
4177330f729Sjoerg 
4187330f729Sjoerg       SourceLocation LocEnd = Region.getEndLoc();
4197330f729Sjoerg       assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
4207330f729Sjoerg              "region spans multiple files");
4217330f729Sjoerg 
4227330f729Sjoerg       // Don't add code regions for the area covered by expansion regions.
4237330f729Sjoerg       // This not only suppresses redundant regions, but sometimes prevents
4247330f729Sjoerg       // creating regions with wrong counters if, for example, a statement's
4257330f729Sjoerg       // body ends at the end of a nested macro.
4267330f729Sjoerg       if (Filter.count(std::make_pair(LocStart, LocEnd)))
4277330f729Sjoerg         continue;
4287330f729Sjoerg 
4297330f729Sjoerg       // Find the spelling locations for the mapping region.
4307330f729Sjoerg       SpellingRegion SR{SM, LocStart, LocEnd};
4317330f729Sjoerg       assert(SR.isInSourceOrder() && "region start and end out of order");
4327330f729Sjoerg 
4337330f729Sjoerg       if (Region.isGap()) {
4347330f729Sjoerg         MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
4357330f729Sjoerg             Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
4367330f729Sjoerg             SR.LineEnd, SR.ColumnEnd));
437*e038c9c4Sjoerg       } else if (Region.isBranch()) {
438*e038c9c4Sjoerg         MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
439*e038c9c4Sjoerg             Region.getCounter(), Region.getFalseCounter(), *CovFileID,
440*e038c9c4Sjoerg             SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd));
4417330f729Sjoerg       } else {
4427330f729Sjoerg         MappingRegions.push_back(CounterMappingRegion::makeRegion(
4437330f729Sjoerg             Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
4447330f729Sjoerg             SR.LineEnd, SR.ColumnEnd));
4457330f729Sjoerg       }
4467330f729Sjoerg     }
4477330f729Sjoerg   }
4487330f729Sjoerg 
4497330f729Sjoerg   /// Generate expansion regions for each virtual file we've seen.
emitExpansionRegions()4507330f729Sjoerg   SourceRegionFilter emitExpansionRegions() {
4517330f729Sjoerg     SourceRegionFilter Filter;
4527330f729Sjoerg     for (const auto &FM : FileIDMapping) {
4537330f729Sjoerg       SourceLocation ExpandedLoc = FM.second.second;
4547330f729Sjoerg       SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
4557330f729Sjoerg       if (ParentLoc.isInvalid())
4567330f729Sjoerg         continue;
4577330f729Sjoerg 
4587330f729Sjoerg       auto ParentFileID = getCoverageFileID(ParentLoc);
4597330f729Sjoerg       if (!ParentFileID)
4607330f729Sjoerg         continue;
4617330f729Sjoerg       auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
4627330f729Sjoerg       assert(ExpandedFileID && "expansion in uncovered file");
4637330f729Sjoerg 
4647330f729Sjoerg       SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
4657330f729Sjoerg       assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
4667330f729Sjoerg              "region spans multiple files");
4677330f729Sjoerg       Filter.insert(std::make_pair(ParentLoc, LocEnd));
4687330f729Sjoerg 
4697330f729Sjoerg       SpellingRegion SR{SM, ParentLoc, LocEnd};
4707330f729Sjoerg       assert(SR.isInSourceOrder() && "region start and end out of order");
4717330f729Sjoerg       MappingRegions.push_back(CounterMappingRegion::makeExpansion(
4727330f729Sjoerg           *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
4737330f729Sjoerg           SR.LineEnd, SR.ColumnEnd));
4747330f729Sjoerg     }
4757330f729Sjoerg     return Filter;
4767330f729Sjoerg   }
4777330f729Sjoerg };
4787330f729Sjoerg 
4797330f729Sjoerg /// Creates unreachable coverage regions for the functions that
4807330f729Sjoerg /// are not emitted.
4817330f729Sjoerg struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
EmptyCoverageMappingBuilder__anon8c3eb65b0211::EmptyCoverageMappingBuilder4827330f729Sjoerg   EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
4837330f729Sjoerg                               const LangOptions &LangOpts)
4847330f729Sjoerg       : CoverageMappingBuilder(CVM, SM, LangOpts) {}
4857330f729Sjoerg 
VisitDecl__anon8c3eb65b0211::EmptyCoverageMappingBuilder4867330f729Sjoerg   void VisitDecl(const Decl *D) {
4877330f729Sjoerg     if (!D->hasBody())
4887330f729Sjoerg       return;
4897330f729Sjoerg     auto Body = D->getBody();
4907330f729Sjoerg     SourceLocation Start = getStart(Body);
4917330f729Sjoerg     SourceLocation End = getEnd(Body);
4927330f729Sjoerg     if (!SM.isWrittenInSameFile(Start, End)) {
4937330f729Sjoerg       // Walk up to find the common ancestor.
4947330f729Sjoerg       // Correct the locations accordingly.
4957330f729Sjoerg       FileID StartFileID = SM.getFileID(Start);
4967330f729Sjoerg       FileID EndFileID = SM.getFileID(End);
4977330f729Sjoerg       while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
4987330f729Sjoerg         Start = getIncludeOrExpansionLoc(Start);
4997330f729Sjoerg         assert(Start.isValid() &&
5007330f729Sjoerg                "Declaration start location not nested within a known region");
5017330f729Sjoerg         StartFileID = SM.getFileID(Start);
5027330f729Sjoerg       }
5037330f729Sjoerg       while (StartFileID != EndFileID) {
5047330f729Sjoerg         End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
5057330f729Sjoerg         assert(End.isValid() &&
5067330f729Sjoerg                "Declaration end location not nested within a known region");
5077330f729Sjoerg         EndFileID = SM.getFileID(End);
5087330f729Sjoerg       }
5097330f729Sjoerg     }
5107330f729Sjoerg     SourceRegions.emplace_back(Counter(), Start, End);
5117330f729Sjoerg   }
5127330f729Sjoerg 
5137330f729Sjoerg   /// Write the mapping data to the output stream
write__anon8c3eb65b0211::EmptyCoverageMappingBuilder5147330f729Sjoerg   void write(llvm::raw_ostream &OS) {
5157330f729Sjoerg     SmallVector<unsigned, 16> FileIDMapping;
5167330f729Sjoerg     gatherFileIDs(FileIDMapping);
5177330f729Sjoerg     emitSourceRegions(SourceRegionFilter());
5187330f729Sjoerg 
5197330f729Sjoerg     if (MappingRegions.empty())
5207330f729Sjoerg       return;
5217330f729Sjoerg 
5227330f729Sjoerg     CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
5237330f729Sjoerg     Writer.write(OS);
5247330f729Sjoerg   }
5257330f729Sjoerg };
5267330f729Sjoerg 
5277330f729Sjoerg /// A StmtVisitor that creates coverage mapping regions which map
5287330f729Sjoerg /// from the source code locations to the PGO counters.
5297330f729Sjoerg struct CounterCoverageMappingBuilder
5307330f729Sjoerg     : public CoverageMappingBuilder,
5317330f729Sjoerg       public ConstStmtVisitor<CounterCoverageMappingBuilder> {
5327330f729Sjoerg   /// The map of statements to count values.
5337330f729Sjoerg   llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
5347330f729Sjoerg 
5357330f729Sjoerg   /// A stack of currently live regions.
5367330f729Sjoerg   std::vector<SourceMappingRegion> RegionStack;
5377330f729Sjoerg 
5387330f729Sjoerg   CounterExpressionBuilder Builder;
5397330f729Sjoerg 
5407330f729Sjoerg   /// A location in the most recently visited file or macro.
5417330f729Sjoerg   ///
5427330f729Sjoerg   /// This is used to adjust the active source regions appropriately when
5437330f729Sjoerg   /// expressions cross file or macro boundaries.
5447330f729Sjoerg   SourceLocation MostRecentLocation;
5457330f729Sjoerg 
546*e038c9c4Sjoerg   /// Whether the visitor at a terminate statement.
547*e038c9c4Sjoerg   bool HasTerminateStmt = false;
548*e038c9c4Sjoerg 
549*e038c9c4Sjoerg   /// Gap region counter after terminate statement.
550*e038c9c4Sjoerg   Counter GapRegionCounter;
5517330f729Sjoerg 
5527330f729Sjoerg   /// Return a counter for the subtraction of \c RHS from \c LHS
subtractCounters__anon8c3eb65b0211::CounterCoverageMappingBuilder5537330f729Sjoerg   Counter subtractCounters(Counter LHS, Counter RHS) {
5547330f729Sjoerg     return Builder.subtract(LHS, RHS);
5557330f729Sjoerg   }
5567330f729Sjoerg 
5577330f729Sjoerg   /// Return a counter for the sum of \c LHS and \c RHS.
addCounters__anon8c3eb65b0211::CounterCoverageMappingBuilder5587330f729Sjoerg   Counter addCounters(Counter LHS, Counter RHS) {
5597330f729Sjoerg     return Builder.add(LHS, RHS);
5607330f729Sjoerg   }
5617330f729Sjoerg 
addCounters__anon8c3eb65b0211::CounterCoverageMappingBuilder5627330f729Sjoerg   Counter addCounters(Counter C1, Counter C2, Counter C3) {
5637330f729Sjoerg     return addCounters(addCounters(C1, C2), C3);
5647330f729Sjoerg   }
5657330f729Sjoerg 
5667330f729Sjoerg   /// Return the region counter for the given statement.
5677330f729Sjoerg   ///
5687330f729Sjoerg   /// This should only be called on statements that have a dedicated counter.
getRegionCounter__anon8c3eb65b0211::CounterCoverageMappingBuilder5697330f729Sjoerg   Counter getRegionCounter(const Stmt *S) {
5707330f729Sjoerg     return Counter::getCounter(CounterMap[S]);
5717330f729Sjoerg   }
5727330f729Sjoerg 
5737330f729Sjoerg   /// Push a region onto the stack.
5747330f729Sjoerg   ///
5757330f729Sjoerg   /// Returns the index on the stack where the region was pushed. This can be
5767330f729Sjoerg   /// used with popRegions to exit a "scope", ending the region that was pushed.
pushRegion__anon8c3eb65b0211::CounterCoverageMappingBuilder5777330f729Sjoerg   size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
578*e038c9c4Sjoerg                     Optional<SourceLocation> EndLoc = None,
579*e038c9c4Sjoerg                     Optional<Counter> FalseCount = None) {
580*e038c9c4Sjoerg 
581*e038c9c4Sjoerg     if (StartLoc && !FalseCount.hasValue()) {
5827330f729Sjoerg       MostRecentLocation = *StartLoc;
5837330f729Sjoerg     }
584*e038c9c4Sjoerg 
585*e038c9c4Sjoerg     RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc);
5867330f729Sjoerg 
5877330f729Sjoerg     return RegionStack.size() - 1;
5887330f729Sjoerg   }
5897330f729Sjoerg 
locationDepth__anon8c3eb65b0211::CounterCoverageMappingBuilder5907330f729Sjoerg   size_t locationDepth(SourceLocation Loc) {
5917330f729Sjoerg     size_t Depth = 0;
5927330f729Sjoerg     while (Loc.isValid()) {
5937330f729Sjoerg       Loc = getIncludeOrExpansionLoc(Loc);
5947330f729Sjoerg       Depth++;
5957330f729Sjoerg     }
5967330f729Sjoerg     return Depth;
5977330f729Sjoerg   }
5987330f729Sjoerg 
5997330f729Sjoerg   /// Pop regions from the stack into the function's list of regions.
6007330f729Sjoerg   ///
6017330f729Sjoerg   /// Adds all regions from \c ParentIndex to the top of the stack to the
6027330f729Sjoerg   /// function's \c SourceRegions.
popRegions__anon8c3eb65b0211::CounterCoverageMappingBuilder6037330f729Sjoerg   void popRegions(size_t ParentIndex) {
6047330f729Sjoerg     assert(RegionStack.size() >= ParentIndex && "parent not in stack");
6057330f729Sjoerg     while (RegionStack.size() > ParentIndex) {
6067330f729Sjoerg       SourceMappingRegion &Region = RegionStack.back();
6077330f729Sjoerg       if (Region.hasStartLoc()) {
6087330f729Sjoerg         SourceLocation StartLoc = Region.getBeginLoc();
6097330f729Sjoerg         SourceLocation EndLoc = Region.hasEndLoc()
6107330f729Sjoerg                                     ? Region.getEndLoc()
6117330f729Sjoerg                                     : RegionStack[ParentIndex].getEndLoc();
612*e038c9c4Sjoerg         bool isBranch = Region.isBranch();
6137330f729Sjoerg         size_t StartDepth = locationDepth(StartLoc);
6147330f729Sjoerg         size_t EndDepth = locationDepth(EndLoc);
6157330f729Sjoerg         while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
6167330f729Sjoerg           bool UnnestStart = StartDepth >= EndDepth;
6177330f729Sjoerg           bool UnnestEnd = EndDepth >= StartDepth;
6187330f729Sjoerg           if (UnnestEnd) {
619*e038c9c4Sjoerg             // The region ends in a nested file or macro expansion. If the
620*e038c9c4Sjoerg             // region is not a branch region, create a separate region for each
621*e038c9c4Sjoerg             // expansion, and for all regions, update the EndLoc. Branch
622*e038c9c4Sjoerg             // regions should not be split in order to keep a straightforward
623*e038c9c4Sjoerg             // correspondance between the region and its associated branch
624*e038c9c4Sjoerg             // condition, even if the condition spans multiple depths.
6257330f729Sjoerg             SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
6267330f729Sjoerg             assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
6277330f729Sjoerg 
628*e038c9c4Sjoerg             if (!isBranch && !isRegionAlreadyAdded(NestedLoc, EndLoc))
629*e038c9c4Sjoerg               SourceRegions.emplace_back(Region.getCounter(), NestedLoc,
630*e038c9c4Sjoerg                                          EndLoc);
6317330f729Sjoerg 
6327330f729Sjoerg             EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
6337330f729Sjoerg             if (EndLoc.isInvalid())
634*e038c9c4Sjoerg               llvm::report_fatal_error(
635*e038c9c4Sjoerg                   "File exit not handled before popRegions");
6367330f729Sjoerg             EndDepth--;
6377330f729Sjoerg           }
6387330f729Sjoerg           if (UnnestStart) {
639*e038c9c4Sjoerg             // The region ends in a nested file or macro expansion. If the
640*e038c9c4Sjoerg             // region is not a branch region, create a separate region for each
641*e038c9c4Sjoerg             // expansion, and for all regions, update the StartLoc. Branch
642*e038c9c4Sjoerg             // regions should not be split in order to keep a straightforward
643*e038c9c4Sjoerg             // correspondance between the region and its associated branch
644*e038c9c4Sjoerg             // condition, even if the condition spans multiple depths.
6457330f729Sjoerg             SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
6467330f729Sjoerg             assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
6477330f729Sjoerg 
648*e038c9c4Sjoerg             if (!isBranch && !isRegionAlreadyAdded(StartLoc, NestedLoc))
649*e038c9c4Sjoerg               SourceRegions.emplace_back(Region.getCounter(), StartLoc,
650*e038c9c4Sjoerg                                          NestedLoc);
6517330f729Sjoerg 
6527330f729Sjoerg             StartLoc = getIncludeOrExpansionLoc(StartLoc);
6537330f729Sjoerg             if (StartLoc.isInvalid())
654*e038c9c4Sjoerg               llvm::report_fatal_error(
655*e038c9c4Sjoerg                   "File exit not handled before popRegions");
6567330f729Sjoerg             StartDepth--;
6577330f729Sjoerg           }
6587330f729Sjoerg         }
6597330f729Sjoerg         Region.setStartLoc(StartLoc);
6607330f729Sjoerg         Region.setEndLoc(EndLoc);
6617330f729Sjoerg 
662*e038c9c4Sjoerg         if (!isBranch) {
6637330f729Sjoerg           MostRecentLocation = EndLoc;
664*e038c9c4Sjoerg           // If this region happens to span an entire expansion, we need to
665*e038c9c4Sjoerg           // make sure we don't overlap the parent region with it.
6667330f729Sjoerg           if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
6677330f729Sjoerg               EndLoc == getEndOfFileOrMacro(EndLoc))
6687330f729Sjoerg             MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
669*e038c9c4Sjoerg         }
6707330f729Sjoerg 
6717330f729Sjoerg         assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
6727330f729Sjoerg         assert(SpellingRegion(SM, Region).isInSourceOrder());
6737330f729Sjoerg         SourceRegions.push_back(Region);
6747330f729Sjoerg         }
6757330f729Sjoerg       RegionStack.pop_back();
6767330f729Sjoerg     }
6777330f729Sjoerg   }
6787330f729Sjoerg 
6797330f729Sjoerg   /// Return the currently active region.
getRegion__anon8c3eb65b0211::CounterCoverageMappingBuilder6807330f729Sjoerg   SourceMappingRegion &getRegion() {
6817330f729Sjoerg     assert(!RegionStack.empty() && "statement has no region");
6827330f729Sjoerg     return RegionStack.back();
6837330f729Sjoerg   }
6847330f729Sjoerg 
6857330f729Sjoerg   /// Propagate counts through the children of \p S if \p VisitChildren is true.
6867330f729Sjoerg   /// Otherwise, only emit a count for \p S itself.
propagateCounts__anon8c3eb65b0211::CounterCoverageMappingBuilder6877330f729Sjoerg   Counter propagateCounts(Counter TopCount, const Stmt *S,
6887330f729Sjoerg                           bool VisitChildren = true) {
6897330f729Sjoerg     SourceLocation StartLoc = getStart(S);
6907330f729Sjoerg     SourceLocation EndLoc = getEnd(S);
6917330f729Sjoerg     size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
6927330f729Sjoerg     if (VisitChildren)
6937330f729Sjoerg       Visit(S);
6947330f729Sjoerg     Counter ExitCount = getRegion().getCounter();
6957330f729Sjoerg     popRegions(Index);
6967330f729Sjoerg 
6977330f729Sjoerg     // The statement may be spanned by an expansion. Make sure we handle a file
6987330f729Sjoerg     // exit out of this expansion before moving to the next statement.
6997330f729Sjoerg     if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
7007330f729Sjoerg       MostRecentLocation = EndLoc;
7017330f729Sjoerg 
7027330f729Sjoerg     return ExitCount;
7037330f729Sjoerg   }
7047330f729Sjoerg 
705*e038c9c4Sjoerg   /// Determine whether the given condition can be constant folded.
ConditionFoldsToBool__anon8c3eb65b0211::CounterCoverageMappingBuilder706*e038c9c4Sjoerg   bool ConditionFoldsToBool(const Expr *Cond) {
707*e038c9c4Sjoerg     Expr::EvalResult Result;
708*e038c9c4Sjoerg     return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
709*e038c9c4Sjoerg   }
710*e038c9c4Sjoerg 
711*e038c9c4Sjoerg   /// Create a Branch Region around an instrumentable condition for coverage
712*e038c9c4Sjoerg   /// and add it to the function's SourceRegions.  A branch region tracks a
713*e038c9c4Sjoerg   /// "True" counter and a "False" counter for boolean expressions that
714*e038c9c4Sjoerg   /// result in the generation of a branch.
createBranchRegion__anon8c3eb65b0211::CounterCoverageMappingBuilder715*e038c9c4Sjoerg   void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt) {
716*e038c9c4Sjoerg     // Check for NULL conditions.
717*e038c9c4Sjoerg     if (!C)
718*e038c9c4Sjoerg       return;
719*e038c9c4Sjoerg 
720*e038c9c4Sjoerg     // Ensure we are an instrumentable condition (i.e. no "&&" or "||").  Push
721*e038c9c4Sjoerg     // region onto RegionStack but immediately pop it (which adds it to the
722*e038c9c4Sjoerg     // function's SourceRegions) because it doesn't apply to any other source
723*e038c9c4Sjoerg     // code other than the Condition.
724*e038c9c4Sjoerg     if (CodeGenFunction::isInstrumentedCondition(C)) {
725*e038c9c4Sjoerg       // If a condition can fold to true or false, the corresponding branch
726*e038c9c4Sjoerg       // will be removed.  Create a region with both counters hard-coded to
727*e038c9c4Sjoerg       // zero. This allows us to visualize them in a special way.
728*e038c9c4Sjoerg       // Alternatively, we can prevent any optimization done via
729*e038c9c4Sjoerg       // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
730*e038c9c4Sjoerg       // CodeGenFunction.c always returns false, but that is very heavy-handed.
731*e038c9c4Sjoerg       if (ConditionFoldsToBool(C))
732*e038c9c4Sjoerg         popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
733*e038c9c4Sjoerg                               Counter::getZero()));
734*e038c9c4Sjoerg       else
735*e038c9c4Sjoerg         // Otherwise, create a region with the True counter and False counter.
736*e038c9c4Sjoerg         popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt));
737*e038c9c4Sjoerg     }
738*e038c9c4Sjoerg   }
739*e038c9c4Sjoerg 
740*e038c9c4Sjoerg   /// Create a Branch Region around a SwitchCase for code coverage
741*e038c9c4Sjoerg   /// and add it to the function's SourceRegions.
createSwitchCaseRegion__anon8c3eb65b0211::CounterCoverageMappingBuilder742*e038c9c4Sjoerg   void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
743*e038c9c4Sjoerg                               Counter FalseCnt) {
744*e038c9c4Sjoerg     // Push region onto RegionStack but immediately pop it (which adds it to
745*e038c9c4Sjoerg     // the function's SourceRegions) because it doesn't apply to any other
746*e038c9c4Sjoerg     // source other than the SwitchCase.
747*e038c9c4Sjoerg     popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
748*e038c9c4Sjoerg   }
749*e038c9c4Sjoerg 
7507330f729Sjoerg   /// Check whether a region with bounds \c StartLoc and \c EndLoc
7517330f729Sjoerg   /// is already added to \c SourceRegions.
isRegionAlreadyAdded__anon8c3eb65b0211::CounterCoverageMappingBuilder752*e038c9c4Sjoerg   bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
753*e038c9c4Sjoerg                             bool isBranch = false) {
7547330f729Sjoerg     return SourceRegions.rend() !=
7557330f729Sjoerg            std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
7567330f729Sjoerg                         [&](const SourceMappingRegion &Region) {
7577330f729Sjoerg                           return Region.getBeginLoc() == StartLoc &&
758*e038c9c4Sjoerg                                  Region.getEndLoc() == EndLoc &&
759*e038c9c4Sjoerg                                  Region.isBranch() == isBranch;
7607330f729Sjoerg                         });
7617330f729Sjoerg   }
7627330f729Sjoerg 
7637330f729Sjoerg   /// Adjust the most recently visited location to \c EndLoc.
7647330f729Sjoerg   ///
7657330f729Sjoerg   /// This should be used after visiting any statements in non-source order.
adjustForOutOfOrderTraversal__anon8c3eb65b0211::CounterCoverageMappingBuilder7667330f729Sjoerg   void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
7677330f729Sjoerg     MostRecentLocation = EndLoc;
7687330f729Sjoerg     // The code region for a whole macro is created in handleFileExit() when
7697330f729Sjoerg     // it detects exiting of the virtual file of that macro. If we visited
7707330f729Sjoerg     // statements in non-source order, we might already have such a region
7717330f729Sjoerg     // added, for example, if a body of a loop is divided among multiple
7727330f729Sjoerg     // macros. Avoid adding duplicate regions in such case.
7737330f729Sjoerg     if (getRegion().hasEndLoc() &&
7747330f729Sjoerg         MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
7757330f729Sjoerg         isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
776*e038c9c4Sjoerg                              MostRecentLocation, getRegion().isBranch()))
7777330f729Sjoerg       MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
7787330f729Sjoerg   }
7797330f729Sjoerg 
7807330f729Sjoerg   /// Adjust regions and state when \c NewLoc exits a file.
7817330f729Sjoerg   ///
7827330f729Sjoerg   /// If moving from our most recently tracked location to \c NewLoc exits any
7837330f729Sjoerg   /// files, this adjusts our current region stack and creates the file regions
7847330f729Sjoerg   /// for the exited file.
handleFileExit__anon8c3eb65b0211::CounterCoverageMappingBuilder7857330f729Sjoerg   void handleFileExit(SourceLocation NewLoc) {
7867330f729Sjoerg     if (NewLoc.isInvalid() ||
7877330f729Sjoerg         SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
7887330f729Sjoerg       return;
7897330f729Sjoerg 
7907330f729Sjoerg     // If NewLoc is not in a file that contains MostRecentLocation, walk up to
7917330f729Sjoerg     // find the common ancestor.
7927330f729Sjoerg     SourceLocation LCA = NewLoc;
7937330f729Sjoerg     FileID ParentFile = SM.getFileID(LCA);
7947330f729Sjoerg     while (!isNestedIn(MostRecentLocation, ParentFile)) {
7957330f729Sjoerg       LCA = getIncludeOrExpansionLoc(LCA);
7967330f729Sjoerg       if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
7977330f729Sjoerg         // Since there isn't a common ancestor, no file was exited. We just need
7987330f729Sjoerg         // to adjust our location to the new file.
7997330f729Sjoerg         MostRecentLocation = NewLoc;
8007330f729Sjoerg         return;
8017330f729Sjoerg       }
8027330f729Sjoerg       ParentFile = SM.getFileID(LCA);
8037330f729Sjoerg     }
8047330f729Sjoerg 
8057330f729Sjoerg     llvm::SmallSet<SourceLocation, 8> StartLocs;
8067330f729Sjoerg     Optional<Counter> ParentCounter;
8077330f729Sjoerg     for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
8087330f729Sjoerg       if (!I.hasStartLoc())
8097330f729Sjoerg         continue;
8107330f729Sjoerg       SourceLocation Loc = I.getBeginLoc();
8117330f729Sjoerg       if (!isNestedIn(Loc, ParentFile)) {
8127330f729Sjoerg         ParentCounter = I.getCounter();
8137330f729Sjoerg         break;
8147330f729Sjoerg       }
8157330f729Sjoerg 
8167330f729Sjoerg       while (!SM.isInFileID(Loc, ParentFile)) {
8177330f729Sjoerg         // The most nested region for each start location is the one with the
8187330f729Sjoerg         // correct count. We avoid creating redundant regions by stopping once
8197330f729Sjoerg         // we've seen this region.
820*e038c9c4Sjoerg         if (StartLocs.insert(Loc).second) {
821*e038c9c4Sjoerg           if (I.isBranch())
822*e038c9c4Sjoerg             SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(), Loc,
823*e038c9c4Sjoerg                                        getEndOfFileOrMacro(Loc), I.isBranch());
824*e038c9c4Sjoerg           else
8257330f729Sjoerg             SourceRegions.emplace_back(I.getCounter(), Loc,
8267330f729Sjoerg                                        getEndOfFileOrMacro(Loc));
827*e038c9c4Sjoerg         }
8287330f729Sjoerg         Loc = getIncludeOrExpansionLoc(Loc);
8297330f729Sjoerg       }
8307330f729Sjoerg       I.setStartLoc(getPreciseTokenLocEnd(Loc));
8317330f729Sjoerg     }
8327330f729Sjoerg 
8337330f729Sjoerg     if (ParentCounter) {
8347330f729Sjoerg       // If the file is contained completely by another region and doesn't
8357330f729Sjoerg       // immediately start its own region, the whole file gets a region
8367330f729Sjoerg       // corresponding to the parent.
8377330f729Sjoerg       SourceLocation Loc = MostRecentLocation;
8387330f729Sjoerg       while (isNestedIn(Loc, ParentFile)) {
8397330f729Sjoerg         SourceLocation FileStart = getStartOfFileOrMacro(Loc);
8407330f729Sjoerg         if (StartLocs.insert(FileStart).second) {
8417330f729Sjoerg           SourceRegions.emplace_back(*ParentCounter, FileStart,
8427330f729Sjoerg                                      getEndOfFileOrMacro(Loc));
8437330f729Sjoerg           assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder());
8447330f729Sjoerg         }
8457330f729Sjoerg         Loc = getIncludeOrExpansionLoc(Loc);
8467330f729Sjoerg       }
8477330f729Sjoerg     }
8487330f729Sjoerg 
8497330f729Sjoerg     MostRecentLocation = NewLoc;
8507330f729Sjoerg   }
8517330f729Sjoerg 
8527330f729Sjoerg   /// Ensure that \c S is included in the current region.
extendRegion__anon8c3eb65b0211::CounterCoverageMappingBuilder8537330f729Sjoerg   void extendRegion(const Stmt *S) {
8547330f729Sjoerg     SourceMappingRegion &Region = getRegion();
8557330f729Sjoerg     SourceLocation StartLoc = getStart(S);
8567330f729Sjoerg 
8577330f729Sjoerg     handleFileExit(StartLoc);
8587330f729Sjoerg     if (!Region.hasStartLoc())
8597330f729Sjoerg       Region.setStartLoc(StartLoc);
8607330f729Sjoerg   }
8617330f729Sjoerg 
8627330f729Sjoerg   /// Mark \c S as a terminator, starting a zero region.
terminateRegion__anon8c3eb65b0211::CounterCoverageMappingBuilder8637330f729Sjoerg   void terminateRegion(const Stmt *S) {
8647330f729Sjoerg     extendRegion(S);
8657330f729Sjoerg     SourceMappingRegion &Region = getRegion();
8667330f729Sjoerg     SourceLocation EndLoc = getEnd(S);
8677330f729Sjoerg     if (!Region.hasEndLoc())
8687330f729Sjoerg       Region.setEndLoc(EndLoc);
8697330f729Sjoerg     pushRegion(Counter::getZero());
870*e038c9c4Sjoerg     HasTerminateStmt = true;
8717330f729Sjoerg   }
8727330f729Sjoerg 
8737330f729Sjoerg   /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
findGapAreaBetween__anon8c3eb65b0211::CounterCoverageMappingBuilder8747330f729Sjoerg   Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
8757330f729Sjoerg                                            SourceLocation BeforeLoc) {
876*e038c9c4Sjoerg     // If AfterLoc is in function-like macro, use the right parenthesis
877*e038c9c4Sjoerg     // location.
878*e038c9c4Sjoerg     if (AfterLoc.isMacroID()) {
879*e038c9c4Sjoerg       FileID FID = SM.getFileID(AfterLoc);
880*e038c9c4Sjoerg       const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
881*e038c9c4Sjoerg       if (EI->isFunctionMacroExpansion())
882*e038c9c4Sjoerg         AfterLoc = EI->getExpansionLocEnd();
883*e038c9c4Sjoerg     }
884*e038c9c4Sjoerg 
885*e038c9c4Sjoerg     size_t StartDepth = locationDepth(AfterLoc);
886*e038c9c4Sjoerg     size_t EndDepth = locationDepth(BeforeLoc);
887*e038c9c4Sjoerg     while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) {
888*e038c9c4Sjoerg       bool UnnestStart = StartDepth >= EndDepth;
889*e038c9c4Sjoerg       bool UnnestEnd = EndDepth >= StartDepth;
890*e038c9c4Sjoerg       if (UnnestEnd) {
891*e038c9c4Sjoerg         assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
892*e038c9c4Sjoerg                                       BeforeLoc));
893*e038c9c4Sjoerg 
894*e038c9c4Sjoerg         BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
895*e038c9c4Sjoerg         assert(BeforeLoc.isValid());
896*e038c9c4Sjoerg         EndDepth--;
897*e038c9c4Sjoerg       }
898*e038c9c4Sjoerg       if (UnnestStart) {
899*e038c9c4Sjoerg         assert(SM.isWrittenInSameFile(AfterLoc,
900*e038c9c4Sjoerg                                       getEndOfFileOrMacro(AfterLoc)));
901*e038c9c4Sjoerg 
902*e038c9c4Sjoerg         AfterLoc = getIncludeOrExpansionLoc(AfterLoc);
903*e038c9c4Sjoerg         assert(AfterLoc.isValid());
904*e038c9c4Sjoerg         AfterLoc = getPreciseTokenLocEnd(AfterLoc);
905*e038c9c4Sjoerg         assert(AfterLoc.isValid());
906*e038c9c4Sjoerg         StartDepth--;
907*e038c9c4Sjoerg       }
908*e038c9c4Sjoerg     }
909*e038c9c4Sjoerg     AfterLoc = getPreciseTokenLocEnd(AfterLoc);
9107330f729Sjoerg     // If the start and end locations of the gap are both within the same macro
9117330f729Sjoerg     // file, the range may not be in source order.
9127330f729Sjoerg     if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
9137330f729Sjoerg       return None;
914*e038c9c4Sjoerg     if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
915*e038c9c4Sjoerg         !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
9167330f729Sjoerg       return None;
9177330f729Sjoerg     return {{AfterLoc, BeforeLoc}};
9187330f729Sjoerg   }
9197330f729Sjoerg 
9207330f729Sjoerg   /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
fillGapAreaWithCount__anon8c3eb65b0211::CounterCoverageMappingBuilder9217330f729Sjoerg   void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
9227330f729Sjoerg                             Counter Count) {
9237330f729Sjoerg     if (StartLoc == EndLoc)
9247330f729Sjoerg       return;
9257330f729Sjoerg     assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
9267330f729Sjoerg     handleFileExit(StartLoc);
9277330f729Sjoerg     size_t Index = pushRegion(Count, StartLoc, EndLoc);
9287330f729Sjoerg     getRegion().setGap(true);
9297330f729Sjoerg     handleFileExit(EndLoc);
9307330f729Sjoerg     popRegions(Index);
9317330f729Sjoerg   }
9327330f729Sjoerg 
9337330f729Sjoerg   /// Keep counts of breaks and continues inside loops.
9347330f729Sjoerg   struct BreakContinue {
9357330f729Sjoerg     Counter BreakCount;
9367330f729Sjoerg     Counter ContinueCount;
9377330f729Sjoerg   };
9387330f729Sjoerg   SmallVector<BreakContinue, 8> BreakContinueStack;
9397330f729Sjoerg 
CounterCoverageMappingBuilder__anon8c3eb65b0211::CounterCoverageMappingBuilder9407330f729Sjoerg   CounterCoverageMappingBuilder(
9417330f729Sjoerg       CoverageMappingModuleGen &CVM,
9427330f729Sjoerg       llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
9437330f729Sjoerg       const LangOptions &LangOpts)
944*e038c9c4Sjoerg       : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
9457330f729Sjoerg 
9467330f729Sjoerg   /// Write the mapping data to the output stream
write__anon8c3eb65b0211::CounterCoverageMappingBuilder9477330f729Sjoerg   void write(llvm::raw_ostream &OS) {
9487330f729Sjoerg     llvm::SmallVector<unsigned, 8> VirtualFileMapping;
9497330f729Sjoerg     gatherFileIDs(VirtualFileMapping);
9507330f729Sjoerg     SourceRegionFilter Filter = emitExpansionRegions();
9517330f729Sjoerg     emitSourceRegions(Filter);
9527330f729Sjoerg     gatherSkippedRegions();
9537330f729Sjoerg 
9547330f729Sjoerg     if (MappingRegions.empty())
9557330f729Sjoerg       return;
9567330f729Sjoerg 
9577330f729Sjoerg     CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
9587330f729Sjoerg                                  MappingRegions);
9597330f729Sjoerg     Writer.write(OS);
9607330f729Sjoerg   }
9617330f729Sjoerg 
VisitStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder9627330f729Sjoerg   void VisitStmt(const Stmt *S) {
9637330f729Sjoerg     if (S->getBeginLoc().isValid())
9647330f729Sjoerg       extendRegion(S);
965*e038c9c4Sjoerg     const Stmt *LastStmt = nullptr;
966*e038c9c4Sjoerg     bool SaveTerminateStmt = HasTerminateStmt;
967*e038c9c4Sjoerg     HasTerminateStmt = false;
968*e038c9c4Sjoerg     GapRegionCounter = Counter::getZero();
9697330f729Sjoerg     for (const Stmt *Child : S->children())
970*e038c9c4Sjoerg       if (Child) {
971*e038c9c4Sjoerg         // If last statement contains terminate statements, add a gap area
972*e038c9c4Sjoerg         // between the two statements. Skipping attributed statements, because
973*e038c9c4Sjoerg         // they don't have valid start location.
974*e038c9c4Sjoerg         if (LastStmt && HasTerminateStmt && !dyn_cast<AttributedStmt>(Child)) {
975*e038c9c4Sjoerg           auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
976*e038c9c4Sjoerg           if (Gap)
977*e038c9c4Sjoerg             fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
978*e038c9c4Sjoerg                                  GapRegionCounter);
979*e038c9c4Sjoerg           SaveTerminateStmt = true;
980*e038c9c4Sjoerg           HasTerminateStmt = false;
981*e038c9c4Sjoerg         }
9827330f729Sjoerg         this->Visit(Child);
983*e038c9c4Sjoerg         LastStmt = Child;
984*e038c9c4Sjoerg       }
985*e038c9c4Sjoerg     if (SaveTerminateStmt)
986*e038c9c4Sjoerg       HasTerminateStmt = true;
9877330f729Sjoerg     handleFileExit(getEnd(S));
9887330f729Sjoerg   }
9897330f729Sjoerg 
VisitDecl__anon8c3eb65b0211::CounterCoverageMappingBuilder9907330f729Sjoerg   void VisitDecl(const Decl *D) {
9917330f729Sjoerg     Stmt *Body = D->getBody();
9927330f729Sjoerg 
9937330f729Sjoerg     // Do not propagate region counts into system headers.
9947330f729Sjoerg     if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
9957330f729Sjoerg       return;
9967330f729Sjoerg 
9977330f729Sjoerg     // Do not visit the artificial children nodes of defaulted methods. The
9987330f729Sjoerg     // lexer may not be able to report back precise token end locations for
9997330f729Sjoerg     // these children nodes (llvm.org/PR39822), and moreover users will not be
10007330f729Sjoerg     // able to see coverage for them.
10017330f729Sjoerg     bool Defaulted = false;
10027330f729Sjoerg     if (auto *Method = dyn_cast<CXXMethodDecl>(D))
10037330f729Sjoerg       Defaulted = Method->isDefaulted();
10047330f729Sjoerg 
10057330f729Sjoerg     propagateCounts(getRegionCounter(Body), Body,
10067330f729Sjoerg                     /*VisitChildren=*/!Defaulted);
10077330f729Sjoerg     assert(RegionStack.empty() && "Regions entered but never exited");
10087330f729Sjoerg   }
10097330f729Sjoerg 
VisitReturnStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder10107330f729Sjoerg   void VisitReturnStmt(const ReturnStmt *S) {
10117330f729Sjoerg     extendRegion(S);
10127330f729Sjoerg     if (S->getRetValue())
10137330f729Sjoerg       Visit(S->getRetValue());
10147330f729Sjoerg     terminateRegion(S);
10157330f729Sjoerg   }
10167330f729Sjoerg 
VisitCoroutineBodyStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder1017*e038c9c4Sjoerg   void VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
1018*e038c9c4Sjoerg     extendRegion(S);
1019*e038c9c4Sjoerg     Visit(S->getBody());
1020*e038c9c4Sjoerg   }
1021*e038c9c4Sjoerg 
VisitCoreturnStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder1022*e038c9c4Sjoerg   void VisitCoreturnStmt(const CoreturnStmt *S) {
1023*e038c9c4Sjoerg     extendRegion(S);
1024*e038c9c4Sjoerg     if (S->getOperand())
1025*e038c9c4Sjoerg       Visit(S->getOperand());
1026*e038c9c4Sjoerg     terminateRegion(S);
1027*e038c9c4Sjoerg   }
1028*e038c9c4Sjoerg 
VisitCXXThrowExpr__anon8c3eb65b0211::CounterCoverageMappingBuilder10297330f729Sjoerg   void VisitCXXThrowExpr(const CXXThrowExpr *E) {
10307330f729Sjoerg     extendRegion(E);
10317330f729Sjoerg     if (E->getSubExpr())
10327330f729Sjoerg       Visit(E->getSubExpr());
10337330f729Sjoerg     terminateRegion(E);
10347330f729Sjoerg   }
10357330f729Sjoerg 
VisitGotoStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder10367330f729Sjoerg   void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
10377330f729Sjoerg 
VisitLabelStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder10387330f729Sjoerg   void VisitLabelStmt(const LabelStmt *S) {
10397330f729Sjoerg     Counter LabelCount = getRegionCounter(S);
10407330f729Sjoerg     SourceLocation Start = getStart(S);
10417330f729Sjoerg     // We can't extendRegion here or we risk overlapping with our new region.
10427330f729Sjoerg     handleFileExit(Start);
10437330f729Sjoerg     pushRegion(LabelCount, Start);
10447330f729Sjoerg     Visit(S->getSubStmt());
10457330f729Sjoerg   }
10467330f729Sjoerg 
VisitBreakStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder10477330f729Sjoerg   void VisitBreakStmt(const BreakStmt *S) {
10487330f729Sjoerg     assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
10497330f729Sjoerg     BreakContinueStack.back().BreakCount = addCounters(
10507330f729Sjoerg         BreakContinueStack.back().BreakCount, getRegion().getCounter());
10517330f729Sjoerg     // FIXME: a break in a switch should terminate regions for all preceding
10527330f729Sjoerg     // case statements, not just the most recent one.
10537330f729Sjoerg     terminateRegion(S);
10547330f729Sjoerg   }
10557330f729Sjoerg 
VisitContinueStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder10567330f729Sjoerg   void VisitContinueStmt(const ContinueStmt *S) {
10577330f729Sjoerg     assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
10587330f729Sjoerg     BreakContinueStack.back().ContinueCount = addCounters(
10597330f729Sjoerg         BreakContinueStack.back().ContinueCount, getRegion().getCounter());
10607330f729Sjoerg     terminateRegion(S);
10617330f729Sjoerg   }
10627330f729Sjoerg 
VisitCallExpr__anon8c3eb65b0211::CounterCoverageMappingBuilder10637330f729Sjoerg   void VisitCallExpr(const CallExpr *E) {
10647330f729Sjoerg     VisitStmt(E);
10657330f729Sjoerg 
10667330f729Sjoerg     // Terminate the region when we hit a noreturn function.
10677330f729Sjoerg     // (This is helpful dealing with switch statements.)
10687330f729Sjoerg     QualType CalleeType = E->getCallee()->getType();
10697330f729Sjoerg     if (getFunctionExtInfo(*CalleeType).getNoReturn())
10707330f729Sjoerg       terminateRegion(E);
10717330f729Sjoerg   }
10727330f729Sjoerg 
VisitWhileStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder10737330f729Sjoerg   void VisitWhileStmt(const WhileStmt *S) {
10747330f729Sjoerg     extendRegion(S);
10757330f729Sjoerg 
10767330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
10777330f729Sjoerg     Counter BodyCount = getRegionCounter(S);
10787330f729Sjoerg 
10797330f729Sjoerg     // Handle the body first so that we can get the backedge count.
10807330f729Sjoerg     BreakContinueStack.push_back(BreakContinue());
10817330f729Sjoerg     extendRegion(S->getBody());
10827330f729Sjoerg     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
10837330f729Sjoerg     BreakContinue BC = BreakContinueStack.pop_back_val();
10847330f729Sjoerg 
1085*e038c9c4Sjoerg     bool BodyHasTerminateStmt = HasTerminateStmt;
1086*e038c9c4Sjoerg     HasTerminateStmt = false;
1087*e038c9c4Sjoerg 
10887330f729Sjoerg     // Go back to handle the condition.
10897330f729Sjoerg     Counter CondCount =
10907330f729Sjoerg         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
10917330f729Sjoerg     propagateCounts(CondCount, S->getCond());
10927330f729Sjoerg     adjustForOutOfOrderTraversal(getEnd(S));
10937330f729Sjoerg 
10947330f729Sjoerg     // The body count applies to the area immediately after the increment.
1095*e038c9c4Sjoerg     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
10967330f729Sjoerg     if (Gap)
10977330f729Sjoerg       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
10987330f729Sjoerg 
10997330f729Sjoerg     Counter OutCount =
11007330f729Sjoerg         addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1101*e038c9c4Sjoerg     if (OutCount != ParentCount) {
11027330f729Sjoerg       pushRegion(OutCount);
1103*e038c9c4Sjoerg       GapRegionCounter = OutCount;
1104*e038c9c4Sjoerg       if (BodyHasTerminateStmt)
1105*e038c9c4Sjoerg         HasTerminateStmt = true;
1106*e038c9c4Sjoerg     }
1107*e038c9c4Sjoerg 
1108*e038c9c4Sjoerg     // Create Branch Region around condition.
1109*e038c9c4Sjoerg     createBranchRegion(S->getCond(), BodyCount,
1110*e038c9c4Sjoerg                        subtractCounters(CondCount, BodyCount));
11117330f729Sjoerg   }
11127330f729Sjoerg 
VisitDoStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder11137330f729Sjoerg   void VisitDoStmt(const DoStmt *S) {
11147330f729Sjoerg     extendRegion(S);
11157330f729Sjoerg 
11167330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
11177330f729Sjoerg     Counter BodyCount = getRegionCounter(S);
11187330f729Sjoerg 
11197330f729Sjoerg     BreakContinueStack.push_back(BreakContinue());
11207330f729Sjoerg     extendRegion(S->getBody());
11217330f729Sjoerg     Counter BackedgeCount =
11227330f729Sjoerg         propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
11237330f729Sjoerg     BreakContinue BC = BreakContinueStack.pop_back_val();
11247330f729Sjoerg 
1125*e038c9c4Sjoerg     bool BodyHasTerminateStmt = HasTerminateStmt;
1126*e038c9c4Sjoerg     HasTerminateStmt = false;
1127*e038c9c4Sjoerg 
11287330f729Sjoerg     Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
11297330f729Sjoerg     propagateCounts(CondCount, S->getCond());
11307330f729Sjoerg 
11317330f729Sjoerg     Counter OutCount =
11327330f729Sjoerg         addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1133*e038c9c4Sjoerg     if (OutCount != ParentCount) {
11347330f729Sjoerg       pushRegion(OutCount);
1135*e038c9c4Sjoerg       GapRegionCounter = OutCount;
1136*e038c9c4Sjoerg     }
1137*e038c9c4Sjoerg 
1138*e038c9c4Sjoerg     // Create Branch Region around condition.
1139*e038c9c4Sjoerg     createBranchRegion(S->getCond(), BodyCount,
1140*e038c9c4Sjoerg                        subtractCounters(CondCount, BodyCount));
1141*e038c9c4Sjoerg 
1142*e038c9c4Sjoerg     if (BodyHasTerminateStmt)
1143*e038c9c4Sjoerg       HasTerminateStmt = true;
11447330f729Sjoerg   }
11457330f729Sjoerg 
VisitForStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder11467330f729Sjoerg   void VisitForStmt(const ForStmt *S) {
11477330f729Sjoerg     extendRegion(S);
11487330f729Sjoerg     if (S->getInit())
11497330f729Sjoerg       Visit(S->getInit());
11507330f729Sjoerg 
11517330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
11527330f729Sjoerg     Counter BodyCount = getRegionCounter(S);
11537330f729Sjoerg 
11547330f729Sjoerg     // The loop increment may contain a break or continue.
11557330f729Sjoerg     if (S->getInc())
11567330f729Sjoerg       BreakContinueStack.emplace_back();
11577330f729Sjoerg 
11587330f729Sjoerg     // Handle the body first so that we can get the backedge count.
11597330f729Sjoerg     BreakContinueStack.emplace_back();
11607330f729Sjoerg     extendRegion(S->getBody());
11617330f729Sjoerg     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
11627330f729Sjoerg     BreakContinue BodyBC = BreakContinueStack.pop_back_val();
11637330f729Sjoerg 
1164*e038c9c4Sjoerg     bool BodyHasTerminateStmt = HasTerminateStmt;
1165*e038c9c4Sjoerg     HasTerminateStmt = false;
1166*e038c9c4Sjoerg 
11677330f729Sjoerg     // The increment is essentially part of the body but it needs to include
11687330f729Sjoerg     // the count for all the continue statements.
11697330f729Sjoerg     BreakContinue IncrementBC;
11707330f729Sjoerg     if (const Stmt *Inc = S->getInc()) {
11717330f729Sjoerg       propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
11727330f729Sjoerg       IncrementBC = BreakContinueStack.pop_back_val();
11737330f729Sjoerg     }
11747330f729Sjoerg 
11757330f729Sjoerg     // Go back to handle the condition.
11767330f729Sjoerg     Counter CondCount = addCounters(
11777330f729Sjoerg         addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
11787330f729Sjoerg         IncrementBC.ContinueCount);
11797330f729Sjoerg     if (const Expr *Cond = S->getCond()) {
11807330f729Sjoerg       propagateCounts(CondCount, Cond);
11817330f729Sjoerg       adjustForOutOfOrderTraversal(getEnd(S));
11827330f729Sjoerg     }
11837330f729Sjoerg 
11847330f729Sjoerg     // The body count applies to the area immediately after the increment.
1185*e038c9c4Sjoerg     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
11867330f729Sjoerg     if (Gap)
11877330f729Sjoerg       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
11887330f729Sjoerg 
11897330f729Sjoerg     Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
11907330f729Sjoerg                                    subtractCounters(CondCount, BodyCount));
1191*e038c9c4Sjoerg     if (OutCount != ParentCount) {
11927330f729Sjoerg       pushRegion(OutCount);
1193*e038c9c4Sjoerg       GapRegionCounter = OutCount;
1194*e038c9c4Sjoerg       if (BodyHasTerminateStmt)
1195*e038c9c4Sjoerg         HasTerminateStmt = true;
1196*e038c9c4Sjoerg     }
1197*e038c9c4Sjoerg 
1198*e038c9c4Sjoerg     // Create Branch Region around condition.
1199*e038c9c4Sjoerg     createBranchRegion(S->getCond(), BodyCount,
1200*e038c9c4Sjoerg                        subtractCounters(CondCount, BodyCount));
12017330f729Sjoerg   }
12027330f729Sjoerg 
VisitCXXForRangeStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder12037330f729Sjoerg   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
12047330f729Sjoerg     extendRegion(S);
12057330f729Sjoerg     if (S->getInit())
12067330f729Sjoerg       Visit(S->getInit());
12077330f729Sjoerg     Visit(S->getLoopVarStmt());
12087330f729Sjoerg     Visit(S->getRangeStmt());
12097330f729Sjoerg 
12107330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
12117330f729Sjoerg     Counter BodyCount = getRegionCounter(S);
12127330f729Sjoerg 
12137330f729Sjoerg     BreakContinueStack.push_back(BreakContinue());
12147330f729Sjoerg     extendRegion(S->getBody());
12157330f729Sjoerg     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
12167330f729Sjoerg     BreakContinue BC = BreakContinueStack.pop_back_val();
12177330f729Sjoerg 
1218*e038c9c4Sjoerg     bool BodyHasTerminateStmt = HasTerminateStmt;
1219*e038c9c4Sjoerg     HasTerminateStmt = false;
1220*e038c9c4Sjoerg 
12217330f729Sjoerg     // The body count applies to the area immediately after the range.
1222*e038c9c4Sjoerg     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
12237330f729Sjoerg     if (Gap)
12247330f729Sjoerg       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
12257330f729Sjoerg 
12267330f729Sjoerg     Counter LoopCount =
12277330f729Sjoerg         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
12287330f729Sjoerg     Counter OutCount =
12297330f729Sjoerg         addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1230*e038c9c4Sjoerg     if (OutCount != ParentCount) {
12317330f729Sjoerg       pushRegion(OutCount);
1232*e038c9c4Sjoerg       GapRegionCounter = OutCount;
1233*e038c9c4Sjoerg       if (BodyHasTerminateStmt)
1234*e038c9c4Sjoerg         HasTerminateStmt = true;
1235*e038c9c4Sjoerg     }
1236*e038c9c4Sjoerg 
1237*e038c9c4Sjoerg     // Create Branch Region around condition.
1238*e038c9c4Sjoerg     createBranchRegion(S->getCond(), BodyCount,
1239*e038c9c4Sjoerg                        subtractCounters(LoopCount, BodyCount));
12407330f729Sjoerg   }
12417330f729Sjoerg 
VisitObjCForCollectionStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder12427330f729Sjoerg   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
12437330f729Sjoerg     extendRegion(S);
12447330f729Sjoerg     Visit(S->getElement());
12457330f729Sjoerg 
12467330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
12477330f729Sjoerg     Counter BodyCount = getRegionCounter(S);
12487330f729Sjoerg 
12497330f729Sjoerg     BreakContinueStack.push_back(BreakContinue());
12507330f729Sjoerg     extendRegion(S->getBody());
12517330f729Sjoerg     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
12527330f729Sjoerg     BreakContinue BC = BreakContinueStack.pop_back_val();
12537330f729Sjoerg 
12547330f729Sjoerg     // The body count applies to the area immediately after the collection.
1255*e038c9c4Sjoerg     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
12567330f729Sjoerg     if (Gap)
12577330f729Sjoerg       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
12587330f729Sjoerg 
12597330f729Sjoerg     Counter LoopCount =
12607330f729Sjoerg         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
12617330f729Sjoerg     Counter OutCount =
12627330f729Sjoerg         addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1263*e038c9c4Sjoerg     if (OutCount != ParentCount) {
12647330f729Sjoerg       pushRegion(OutCount);
1265*e038c9c4Sjoerg       GapRegionCounter = OutCount;
1266*e038c9c4Sjoerg     }
12677330f729Sjoerg   }
12687330f729Sjoerg 
VisitSwitchStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder12697330f729Sjoerg   void VisitSwitchStmt(const SwitchStmt *S) {
12707330f729Sjoerg     extendRegion(S);
12717330f729Sjoerg     if (S->getInit())
12727330f729Sjoerg       Visit(S->getInit());
12737330f729Sjoerg     Visit(S->getCond());
12747330f729Sjoerg 
12757330f729Sjoerg     BreakContinueStack.push_back(BreakContinue());
12767330f729Sjoerg 
12777330f729Sjoerg     const Stmt *Body = S->getBody();
12787330f729Sjoerg     extendRegion(Body);
12797330f729Sjoerg     if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
12807330f729Sjoerg       if (!CS->body_empty()) {
12817330f729Sjoerg         // Make a region for the body of the switch.  If the body starts with
12827330f729Sjoerg         // a case, that case will reuse this region; otherwise, this covers
12837330f729Sjoerg         // the unreachable code at the beginning of the switch body.
1284*e038c9c4Sjoerg         size_t Index = pushRegion(Counter::getZero(), getStart(CS));
1285*e038c9c4Sjoerg         getRegion().setGap(true);
1286*e038c9c4Sjoerg         Visit(Body);
12877330f729Sjoerg 
12887330f729Sjoerg         // Set the end for the body of the switch, if it isn't already set.
12897330f729Sjoerg         for (size_t i = RegionStack.size(); i != Index; --i) {
12907330f729Sjoerg           if (!RegionStack[i - 1].hasEndLoc())
12917330f729Sjoerg             RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
12927330f729Sjoerg         }
12937330f729Sjoerg 
12947330f729Sjoerg         popRegions(Index);
12957330f729Sjoerg       }
12967330f729Sjoerg     } else
12977330f729Sjoerg       propagateCounts(Counter::getZero(), Body);
12987330f729Sjoerg     BreakContinue BC = BreakContinueStack.pop_back_val();
12997330f729Sjoerg 
13007330f729Sjoerg     if (!BreakContinueStack.empty())
13017330f729Sjoerg       BreakContinueStack.back().ContinueCount = addCounters(
13027330f729Sjoerg           BreakContinueStack.back().ContinueCount, BC.ContinueCount);
13037330f729Sjoerg 
1304*e038c9c4Sjoerg     Counter ParentCount = getRegion().getCounter();
13057330f729Sjoerg     Counter ExitCount = getRegionCounter(S);
13067330f729Sjoerg     SourceLocation ExitLoc = getEnd(S);
13077330f729Sjoerg     pushRegion(ExitCount);
1308*e038c9c4Sjoerg     GapRegionCounter = ExitCount;
13097330f729Sjoerg 
13107330f729Sjoerg     // Ensure that handleFileExit recognizes when the end location is located
13117330f729Sjoerg     // in a different file.
13127330f729Sjoerg     MostRecentLocation = getStart(S);
13137330f729Sjoerg     handleFileExit(ExitLoc);
1314*e038c9c4Sjoerg 
1315*e038c9c4Sjoerg     // Create a Branch Region around each Case. Subtract the case's
1316*e038c9c4Sjoerg     // counter from the Parent counter to track the "False" branch count.
1317*e038c9c4Sjoerg     Counter CaseCountSum;
1318*e038c9c4Sjoerg     bool HasDefaultCase = false;
1319*e038c9c4Sjoerg     const SwitchCase *Case = S->getSwitchCaseList();
1320*e038c9c4Sjoerg     for (; Case; Case = Case->getNextSwitchCase()) {
1321*e038c9c4Sjoerg       HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1322*e038c9c4Sjoerg       CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case));
1323*e038c9c4Sjoerg       createSwitchCaseRegion(
1324*e038c9c4Sjoerg           Case, getRegionCounter(Case),
1325*e038c9c4Sjoerg           subtractCounters(ParentCount, getRegionCounter(Case)));
1326*e038c9c4Sjoerg     }
1327*e038c9c4Sjoerg 
1328*e038c9c4Sjoerg     // If no explicit default case exists, create a branch region to represent
1329*e038c9c4Sjoerg     // the hidden branch, which will be added later by the CodeGen. This region
1330*e038c9c4Sjoerg     // will be associated with the switch statement's condition.
1331*e038c9c4Sjoerg     if (!HasDefaultCase) {
1332*e038c9c4Sjoerg       Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
1333*e038c9c4Sjoerg       Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
1334*e038c9c4Sjoerg       createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
1335*e038c9c4Sjoerg     }
13367330f729Sjoerg   }
13377330f729Sjoerg 
VisitSwitchCase__anon8c3eb65b0211::CounterCoverageMappingBuilder13387330f729Sjoerg   void VisitSwitchCase(const SwitchCase *S) {
13397330f729Sjoerg     extendRegion(S);
13407330f729Sjoerg 
13417330f729Sjoerg     SourceMappingRegion &Parent = getRegion();
13427330f729Sjoerg 
13437330f729Sjoerg     Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
13447330f729Sjoerg     // Reuse the existing region if it starts at our label. This is typical of
13457330f729Sjoerg     // the first case in a switch.
13467330f729Sjoerg     if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
13477330f729Sjoerg       Parent.setCounter(Count);
13487330f729Sjoerg     else
13497330f729Sjoerg       pushRegion(Count, getStart(S));
13507330f729Sjoerg 
1351*e038c9c4Sjoerg     GapRegionCounter = Count;
1352*e038c9c4Sjoerg 
13537330f729Sjoerg     if (const auto *CS = dyn_cast<CaseStmt>(S)) {
13547330f729Sjoerg       Visit(CS->getLHS());
13557330f729Sjoerg       if (const Expr *RHS = CS->getRHS())
13567330f729Sjoerg         Visit(RHS);
13577330f729Sjoerg     }
13587330f729Sjoerg     Visit(S->getSubStmt());
13597330f729Sjoerg   }
13607330f729Sjoerg 
VisitIfStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder13617330f729Sjoerg   void VisitIfStmt(const IfStmt *S) {
13627330f729Sjoerg     extendRegion(S);
13637330f729Sjoerg     if (S->getInit())
13647330f729Sjoerg       Visit(S->getInit());
13657330f729Sjoerg 
13667330f729Sjoerg     // Extend into the condition before we propagate through it below - this is
13677330f729Sjoerg     // needed to handle macros that generate the "if" but not the condition.
13687330f729Sjoerg     extendRegion(S->getCond());
13697330f729Sjoerg 
13707330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
13717330f729Sjoerg     Counter ThenCount = getRegionCounter(S);
13727330f729Sjoerg 
13737330f729Sjoerg     // Emitting a counter for the condition makes it easier to interpret the
13747330f729Sjoerg     // counter for the body when looking at the coverage.
13757330f729Sjoerg     propagateCounts(ParentCount, S->getCond());
13767330f729Sjoerg 
13777330f729Sjoerg     // The 'then' count applies to the area immediately after the condition.
1378*e038c9c4Sjoerg     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
13797330f729Sjoerg     if (Gap)
13807330f729Sjoerg       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
13817330f729Sjoerg 
13827330f729Sjoerg     extendRegion(S->getThen());
13837330f729Sjoerg     Counter OutCount = propagateCounts(ThenCount, S->getThen());
13847330f729Sjoerg 
13857330f729Sjoerg     Counter ElseCount = subtractCounters(ParentCount, ThenCount);
13867330f729Sjoerg     if (const Stmt *Else = S->getElse()) {
1387*e038c9c4Sjoerg       bool ThenHasTerminateStmt = HasTerminateStmt;
1388*e038c9c4Sjoerg       HasTerminateStmt = false;
1389*e038c9c4Sjoerg 
13907330f729Sjoerg       // The 'else' count applies to the area immediately after the 'then'.
1391*e038c9c4Sjoerg       Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
13927330f729Sjoerg       if (Gap)
13937330f729Sjoerg         fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
13947330f729Sjoerg       extendRegion(Else);
13957330f729Sjoerg       OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1396*e038c9c4Sjoerg 
1397*e038c9c4Sjoerg       if (ThenHasTerminateStmt)
1398*e038c9c4Sjoerg         HasTerminateStmt = true;
13997330f729Sjoerg     } else
14007330f729Sjoerg       OutCount = addCounters(OutCount, ElseCount);
14017330f729Sjoerg 
1402*e038c9c4Sjoerg     if (OutCount != ParentCount) {
14037330f729Sjoerg       pushRegion(OutCount);
1404*e038c9c4Sjoerg       GapRegionCounter = OutCount;
1405*e038c9c4Sjoerg     }
1406*e038c9c4Sjoerg 
1407*e038c9c4Sjoerg     // Create Branch Region around condition.
1408*e038c9c4Sjoerg     createBranchRegion(S->getCond(), ThenCount,
1409*e038c9c4Sjoerg                        subtractCounters(ParentCount, ThenCount));
14107330f729Sjoerg   }
14117330f729Sjoerg 
VisitCXXTryStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder14127330f729Sjoerg   void VisitCXXTryStmt(const CXXTryStmt *S) {
14137330f729Sjoerg     extendRegion(S);
14147330f729Sjoerg     // Handle macros that generate the "try" but not the rest.
14157330f729Sjoerg     extendRegion(S->getTryBlock());
14167330f729Sjoerg 
14177330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
14187330f729Sjoerg     propagateCounts(ParentCount, S->getTryBlock());
14197330f729Sjoerg 
14207330f729Sjoerg     for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
14217330f729Sjoerg       Visit(S->getHandler(I));
14227330f729Sjoerg 
14237330f729Sjoerg     Counter ExitCount = getRegionCounter(S);
14247330f729Sjoerg     pushRegion(ExitCount);
14257330f729Sjoerg   }
14267330f729Sjoerg 
VisitCXXCatchStmt__anon8c3eb65b0211::CounterCoverageMappingBuilder14277330f729Sjoerg   void VisitCXXCatchStmt(const CXXCatchStmt *S) {
14287330f729Sjoerg     propagateCounts(getRegionCounter(S), S->getHandlerBlock());
14297330f729Sjoerg   }
14307330f729Sjoerg 
VisitAbstractConditionalOperator__anon8c3eb65b0211::CounterCoverageMappingBuilder14317330f729Sjoerg   void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
14327330f729Sjoerg     extendRegion(E);
14337330f729Sjoerg 
14347330f729Sjoerg     Counter ParentCount = getRegion().getCounter();
14357330f729Sjoerg     Counter TrueCount = getRegionCounter(E);
14367330f729Sjoerg 
1437*e038c9c4Sjoerg     propagateCounts(ParentCount, E->getCond());
14387330f729Sjoerg 
14397330f729Sjoerg     if (!isa<BinaryConditionalOperator>(E)) {
14407330f729Sjoerg       // The 'then' count applies to the area immediately after the condition.
14417330f729Sjoerg       auto Gap =
14427330f729Sjoerg           findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
14437330f729Sjoerg       if (Gap)
14447330f729Sjoerg         fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
14457330f729Sjoerg 
14467330f729Sjoerg       extendRegion(E->getTrueExpr());
14477330f729Sjoerg       propagateCounts(TrueCount, E->getTrueExpr());
14487330f729Sjoerg     }
14497330f729Sjoerg 
14507330f729Sjoerg     extendRegion(E->getFalseExpr());
14517330f729Sjoerg     propagateCounts(subtractCounters(ParentCount, TrueCount),
14527330f729Sjoerg                     E->getFalseExpr());
1453*e038c9c4Sjoerg 
1454*e038c9c4Sjoerg     // Create Branch Region around condition.
1455*e038c9c4Sjoerg     createBranchRegion(E->getCond(), TrueCount,
1456*e038c9c4Sjoerg                        subtractCounters(ParentCount, TrueCount));
14577330f729Sjoerg   }
14587330f729Sjoerg 
VisitBinLAnd__anon8c3eb65b0211::CounterCoverageMappingBuilder14597330f729Sjoerg   void VisitBinLAnd(const BinaryOperator *E) {
14607330f729Sjoerg     extendRegion(E->getLHS());
14617330f729Sjoerg     propagateCounts(getRegion().getCounter(), E->getLHS());
14627330f729Sjoerg     handleFileExit(getEnd(E->getLHS()));
14637330f729Sjoerg 
1464*e038c9c4Sjoerg     // Counter tracks the right hand side of a logical and operator.
14657330f729Sjoerg     extendRegion(E->getRHS());
14667330f729Sjoerg     propagateCounts(getRegionCounter(E), E->getRHS());
1467*e038c9c4Sjoerg 
1468*e038c9c4Sjoerg     // Extract the RHS's Execution Counter.
1469*e038c9c4Sjoerg     Counter RHSExecCnt = getRegionCounter(E);
1470*e038c9c4Sjoerg 
1471*e038c9c4Sjoerg     // Extract the RHS's "True" Instance Counter.
1472*e038c9c4Sjoerg     Counter RHSTrueCnt = getRegionCounter(E->getRHS());
1473*e038c9c4Sjoerg 
1474*e038c9c4Sjoerg     // Extract the Parent Region Counter.
1475*e038c9c4Sjoerg     Counter ParentCnt = getRegion().getCounter();
1476*e038c9c4Sjoerg 
1477*e038c9c4Sjoerg     // Create Branch Region around LHS condition.
1478*e038c9c4Sjoerg     createBranchRegion(E->getLHS(), RHSExecCnt,
1479*e038c9c4Sjoerg                        subtractCounters(ParentCnt, RHSExecCnt));
1480*e038c9c4Sjoerg 
1481*e038c9c4Sjoerg     // Create Branch Region around RHS condition.
1482*e038c9c4Sjoerg     createBranchRegion(E->getRHS(), RHSTrueCnt,
1483*e038c9c4Sjoerg                        subtractCounters(RHSExecCnt, RHSTrueCnt));
14847330f729Sjoerg   }
14857330f729Sjoerg 
VisitBinLOr__anon8c3eb65b0211::CounterCoverageMappingBuilder14867330f729Sjoerg   void VisitBinLOr(const BinaryOperator *E) {
14877330f729Sjoerg     extendRegion(E->getLHS());
14887330f729Sjoerg     propagateCounts(getRegion().getCounter(), E->getLHS());
14897330f729Sjoerg     handleFileExit(getEnd(E->getLHS()));
14907330f729Sjoerg 
1491*e038c9c4Sjoerg     // Counter tracks the right hand side of a logical or operator.
14927330f729Sjoerg     extendRegion(E->getRHS());
14937330f729Sjoerg     propagateCounts(getRegionCounter(E), E->getRHS());
1494*e038c9c4Sjoerg 
1495*e038c9c4Sjoerg     // Extract the RHS's Execution Counter.
1496*e038c9c4Sjoerg     Counter RHSExecCnt = getRegionCounter(E);
1497*e038c9c4Sjoerg 
1498*e038c9c4Sjoerg     // Extract the RHS's "False" Instance Counter.
1499*e038c9c4Sjoerg     Counter RHSFalseCnt = getRegionCounter(E->getRHS());
1500*e038c9c4Sjoerg 
1501*e038c9c4Sjoerg     // Extract the Parent Region Counter.
1502*e038c9c4Sjoerg     Counter ParentCnt = getRegion().getCounter();
1503*e038c9c4Sjoerg 
1504*e038c9c4Sjoerg     // Create Branch Region around LHS condition.
1505*e038c9c4Sjoerg     createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
1506*e038c9c4Sjoerg                        RHSExecCnt);
1507*e038c9c4Sjoerg 
1508*e038c9c4Sjoerg     // Create Branch Region around RHS condition.
1509*e038c9c4Sjoerg     createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
1510*e038c9c4Sjoerg                        RHSFalseCnt);
15117330f729Sjoerg   }
15127330f729Sjoerg 
VisitLambdaExpr__anon8c3eb65b0211::CounterCoverageMappingBuilder15137330f729Sjoerg   void VisitLambdaExpr(const LambdaExpr *LE) {
15147330f729Sjoerg     // Lambdas are treated as their own functions for now, so we shouldn't
15157330f729Sjoerg     // propagate counts into them.
15167330f729Sjoerg   }
15177330f729Sjoerg };
15187330f729Sjoerg 
15197330f729Sjoerg } // end anonymous namespace
15207330f729Sjoerg 
dump(llvm::raw_ostream & OS,StringRef FunctionName,ArrayRef<CounterExpression> Expressions,ArrayRef<CounterMappingRegion> Regions)15217330f729Sjoerg static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
15227330f729Sjoerg                  ArrayRef<CounterExpression> Expressions,
15237330f729Sjoerg                  ArrayRef<CounterMappingRegion> Regions) {
15247330f729Sjoerg   OS << FunctionName << ":\n";
15257330f729Sjoerg   CounterMappingContext Ctx(Expressions);
15267330f729Sjoerg   for (const auto &R : Regions) {
15277330f729Sjoerg     OS.indent(2);
15287330f729Sjoerg     switch (R.Kind) {
15297330f729Sjoerg     case CounterMappingRegion::CodeRegion:
15307330f729Sjoerg       break;
15317330f729Sjoerg     case CounterMappingRegion::ExpansionRegion:
15327330f729Sjoerg       OS << "Expansion,";
15337330f729Sjoerg       break;
15347330f729Sjoerg     case CounterMappingRegion::SkippedRegion:
15357330f729Sjoerg       OS << "Skipped,";
15367330f729Sjoerg       break;
15377330f729Sjoerg     case CounterMappingRegion::GapRegion:
15387330f729Sjoerg       OS << "Gap,";
15397330f729Sjoerg       break;
1540*e038c9c4Sjoerg     case CounterMappingRegion::BranchRegion:
1541*e038c9c4Sjoerg       OS << "Branch,";
1542*e038c9c4Sjoerg       break;
15437330f729Sjoerg     }
15447330f729Sjoerg 
15457330f729Sjoerg     OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
15467330f729Sjoerg        << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
15477330f729Sjoerg     Ctx.dump(R.Count, OS);
1548*e038c9c4Sjoerg 
1549*e038c9c4Sjoerg     if (R.Kind == CounterMappingRegion::BranchRegion) {
1550*e038c9c4Sjoerg       OS << ", ";
1551*e038c9c4Sjoerg       Ctx.dump(R.FalseCount, OS);
1552*e038c9c4Sjoerg     }
1553*e038c9c4Sjoerg 
15547330f729Sjoerg     if (R.Kind == CounterMappingRegion::ExpansionRegion)
15557330f729Sjoerg       OS << " (Expanded file = " << R.ExpandedFileID << ")";
15567330f729Sjoerg     OS << "\n";
15577330f729Sjoerg   }
15587330f729Sjoerg }
15597330f729Sjoerg 
CoverageMappingModuleGen(CodeGenModule & CGM,CoverageSourceInfo & SourceInfo)1560*e038c9c4Sjoerg CoverageMappingModuleGen::CoverageMappingModuleGen(
1561*e038c9c4Sjoerg     CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
1562*e038c9c4Sjoerg     : CGM(CGM), SourceInfo(SourceInfo) {
1563*e038c9c4Sjoerg   CoveragePrefixMap = CGM.getCodeGenOpts().CoveragePrefixMap;
1564*e038c9c4Sjoerg }
1565*e038c9c4Sjoerg 
getCurrentDirname()1566*e038c9c4Sjoerg std::string CoverageMappingModuleGen::getCurrentDirname() {
1567*e038c9c4Sjoerg   if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
1568*e038c9c4Sjoerg     return CGM.getCodeGenOpts().CoverageCompilationDir;
1569*e038c9c4Sjoerg 
1570*e038c9c4Sjoerg   SmallString<256> CWD;
1571*e038c9c4Sjoerg   llvm::sys::fs::current_path(CWD);
1572*e038c9c4Sjoerg   return CWD.str().str();
1573*e038c9c4Sjoerg }
1574*e038c9c4Sjoerg 
normalizeFilename(StringRef Filename)1575*e038c9c4Sjoerg std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
1576*e038c9c4Sjoerg   llvm::SmallString<256> Path(Filename);
1577*e038c9c4Sjoerg   llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
1578*e038c9c4Sjoerg   for (const auto &Entry : CoveragePrefixMap) {
1579*e038c9c4Sjoerg     if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
1580*e038c9c4Sjoerg       break;
1581*e038c9c4Sjoerg   }
1582*e038c9c4Sjoerg   return Path.str().str();
1583*e038c9c4Sjoerg }
1584*e038c9c4Sjoerg 
getInstrProfSection(const CodeGenModule & CGM,llvm::InstrProfSectKind SK)1585*e038c9c4Sjoerg static std::string getInstrProfSection(const CodeGenModule &CGM,
1586*e038c9c4Sjoerg                                        llvm::InstrProfSectKind SK) {
1587*e038c9c4Sjoerg   return llvm::getInstrProfSectionName(
1588*e038c9c4Sjoerg       SK, CGM.getContext().getTargetInfo().getTriple().getObjectFormat());
1589*e038c9c4Sjoerg }
1590*e038c9c4Sjoerg 
emitFunctionMappingRecord(const FunctionInfo & Info,uint64_t FilenamesRef)1591*e038c9c4Sjoerg void CoverageMappingModuleGen::emitFunctionMappingRecord(
1592*e038c9c4Sjoerg     const FunctionInfo &Info, uint64_t FilenamesRef) {
15937330f729Sjoerg   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1594*e038c9c4Sjoerg 
1595*e038c9c4Sjoerg   // Assign a name to the function record. This is used to merge duplicates.
1596*e038c9c4Sjoerg   std::string FuncRecordName = "__covrec_" + llvm::utohexstr(Info.NameHash);
1597*e038c9c4Sjoerg 
1598*e038c9c4Sjoerg   // A dummy description for a function included-but-not-used in a TU can be
1599*e038c9c4Sjoerg   // replaced by full description provided by a different TU. The two kinds of
1600*e038c9c4Sjoerg   // descriptions play distinct roles: therefore, assign them different names
1601*e038c9c4Sjoerg   // to prevent `linkonce_odr` merging.
1602*e038c9c4Sjoerg   if (Info.IsUsed)
1603*e038c9c4Sjoerg     FuncRecordName += "u";
1604*e038c9c4Sjoerg 
1605*e038c9c4Sjoerg   // Create the function record type.
1606*e038c9c4Sjoerg   const uint64_t NameHash = Info.NameHash;
1607*e038c9c4Sjoerg   const uint64_t FuncHash = Info.FuncHash;
1608*e038c9c4Sjoerg   const std::string &CoverageMapping = Info.CoverageMapping;
16097330f729Sjoerg #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
16107330f729Sjoerg   llvm::Type *FunctionRecordTypes[] = {
16117330f729Sjoerg #include "llvm/ProfileData/InstrProfData.inc"
16127330f729Sjoerg   };
1613*e038c9c4Sjoerg   auto *FunctionRecordTy =
16147330f729Sjoerg       llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
16157330f729Sjoerg                             /*isPacked=*/true);
16167330f729Sjoerg 
1617*e038c9c4Sjoerg   // Create the function record constant.
16187330f729Sjoerg #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
16197330f729Sjoerg   llvm::Constant *FunctionRecordVals[] = {
16207330f729Sjoerg       #include "llvm/ProfileData/InstrProfData.inc"
16217330f729Sjoerg   };
1622*e038c9c4Sjoerg   auto *FuncRecordConstant = llvm::ConstantStruct::get(
1623*e038c9c4Sjoerg       FunctionRecordTy, makeArrayRef(FunctionRecordVals));
1624*e038c9c4Sjoerg 
1625*e038c9c4Sjoerg   // Create the function record global.
1626*e038c9c4Sjoerg   auto *FuncRecord = new llvm::GlobalVariable(
1627*e038c9c4Sjoerg       CGM.getModule(), FunctionRecordTy, /*isConstant=*/true,
1628*e038c9c4Sjoerg       llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant,
1629*e038c9c4Sjoerg       FuncRecordName);
1630*e038c9c4Sjoerg   FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility);
1631*e038c9c4Sjoerg   FuncRecord->setSection(getInstrProfSection(CGM, llvm::IPSK_covfun));
1632*e038c9c4Sjoerg   FuncRecord->setAlignment(llvm::Align(8));
1633*e038c9c4Sjoerg   if (CGM.supportsCOMDAT())
1634*e038c9c4Sjoerg     FuncRecord->setComdat(CGM.getModule().getOrInsertComdat(FuncRecordName));
1635*e038c9c4Sjoerg 
1636*e038c9c4Sjoerg   // Make sure the data doesn't get deleted.
1637*e038c9c4Sjoerg   CGM.addUsedGlobal(FuncRecord);
1638*e038c9c4Sjoerg }
1639*e038c9c4Sjoerg 
addFunctionMappingRecord(llvm::GlobalVariable * NamePtr,StringRef NameValue,uint64_t FuncHash,const std::string & CoverageMapping,bool IsUsed)1640*e038c9c4Sjoerg void CoverageMappingModuleGen::addFunctionMappingRecord(
1641*e038c9c4Sjoerg     llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
1642*e038c9c4Sjoerg     const std::string &CoverageMapping, bool IsUsed) {
1643*e038c9c4Sjoerg   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
1644*e038c9c4Sjoerg   const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
1645*e038c9c4Sjoerg   FunctionRecords.push_back({NameHash, FuncHash, CoverageMapping, IsUsed});
1646*e038c9c4Sjoerg 
16477330f729Sjoerg   if (!IsUsed)
16487330f729Sjoerg     FunctionNames.push_back(
16497330f729Sjoerg         llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
16507330f729Sjoerg 
16517330f729Sjoerg   if (CGM.getCodeGenOpts().DumpCoverageMapping) {
16527330f729Sjoerg     // Dump the coverage mapping data for this function by decoding the
16537330f729Sjoerg     // encoded data. This allows us to dump the mapping regions which were
16547330f729Sjoerg     // also processed by the CoverageMappingWriter which performs
16557330f729Sjoerg     // additional minimization operations such as reducing the number of
16567330f729Sjoerg     // expressions.
1657*e038c9c4Sjoerg     llvm::SmallVector<std::string, 16> FilenameStrs;
16587330f729Sjoerg     std::vector<StringRef> Filenames;
16597330f729Sjoerg     std::vector<CounterExpression> Expressions;
16607330f729Sjoerg     std::vector<CounterMappingRegion> Regions;
1661*e038c9c4Sjoerg     FilenameStrs.resize(FileEntries.size() + 1);
1662*e038c9c4Sjoerg     FilenameStrs[0] = normalizeFilename(getCurrentDirname());
16637330f729Sjoerg     for (const auto &Entry : FileEntries) {
16647330f729Sjoerg       auto I = Entry.second;
16657330f729Sjoerg       FilenameStrs[I] = normalizeFilename(Entry.first->getName());
16667330f729Sjoerg     }
1667*e038c9c4Sjoerg     ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(FilenameStrs);
16687330f729Sjoerg     RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
16697330f729Sjoerg                                     Expressions, Regions);
16707330f729Sjoerg     if (Reader.read())
16717330f729Sjoerg       return;
16727330f729Sjoerg     dump(llvm::outs(), NameValue, Expressions, Regions);
16737330f729Sjoerg   }
16747330f729Sjoerg }
16757330f729Sjoerg 
emit()16767330f729Sjoerg void CoverageMappingModuleGen::emit() {
16777330f729Sjoerg   if (FunctionRecords.empty())
16787330f729Sjoerg     return;
16797330f729Sjoerg   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
16807330f729Sjoerg   auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
16817330f729Sjoerg 
16827330f729Sjoerg   // Create the filenames and merge them with coverage mappings
16837330f729Sjoerg   llvm::SmallVector<std::string, 16> FilenameStrs;
1684*e038c9c4Sjoerg   FilenameStrs.resize(FileEntries.size() + 1);
1685*e038c9c4Sjoerg   // The first filename is the current working directory.
1686*e038c9c4Sjoerg   FilenameStrs[0] = normalizeFilename(getCurrentDirname());
16877330f729Sjoerg   for (const auto &Entry : FileEntries) {
16887330f729Sjoerg     auto I = Entry.second;
16897330f729Sjoerg     FilenameStrs[I] = normalizeFilename(Entry.first->getName());
16907330f729Sjoerg   }
16917330f729Sjoerg 
1692*e038c9c4Sjoerg   std::string Filenames;
1693*e038c9c4Sjoerg   {
1694*e038c9c4Sjoerg     llvm::raw_string_ostream OS(Filenames);
1695*e038c9c4Sjoerg     CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
16967330f729Sjoerg   }
1697*e038c9c4Sjoerg   auto *FilenamesVal =
1698*e038c9c4Sjoerg       llvm::ConstantDataArray::getString(Ctx, Filenames, false);
1699*e038c9c4Sjoerg   const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames);
17007330f729Sjoerg 
1701*e038c9c4Sjoerg   // Emit the function records.
1702*e038c9c4Sjoerg   for (const FunctionInfo &Info : FunctionRecords)
1703*e038c9c4Sjoerg     emitFunctionMappingRecord(Info, FilenamesRef);
17047330f729Sjoerg 
1705*e038c9c4Sjoerg   const unsigned NRecords = 0;
1706*e038c9c4Sjoerg   const size_t FilenamesSize = Filenames.size();
1707*e038c9c4Sjoerg   const unsigned CoverageMappingSize = 0;
17087330f729Sjoerg   llvm::Type *CovDataHeaderTypes[] = {
17097330f729Sjoerg #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
17107330f729Sjoerg #include "llvm/ProfileData/InstrProfData.inc"
17117330f729Sjoerg   };
17127330f729Sjoerg   auto CovDataHeaderTy =
17137330f729Sjoerg       llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
17147330f729Sjoerg   llvm::Constant *CovDataHeaderVals[] = {
17157330f729Sjoerg #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
17167330f729Sjoerg #include "llvm/ProfileData/InstrProfData.inc"
17177330f729Sjoerg   };
17187330f729Sjoerg   auto CovDataHeaderVal = llvm::ConstantStruct::get(
17197330f729Sjoerg       CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
17207330f729Sjoerg 
17217330f729Sjoerg   // Create the coverage data record
1722*e038c9c4Sjoerg   llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()};
17237330f729Sjoerg   auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
1724*e038c9c4Sjoerg   llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal};
17257330f729Sjoerg   auto CovDataVal =
17267330f729Sjoerg       llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
17277330f729Sjoerg   auto CovData = new llvm::GlobalVariable(
1728*e038c9c4Sjoerg       CGM.getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage,
17297330f729Sjoerg       CovDataVal, llvm::getCoverageMappingVarName());
17307330f729Sjoerg 
1731*e038c9c4Sjoerg   CovData->setSection(getInstrProfSection(CGM, llvm::IPSK_covmap));
17327330f729Sjoerg   CovData->setAlignment(llvm::Align(8));
17337330f729Sjoerg 
17347330f729Sjoerg   // Make sure the data doesn't get deleted.
17357330f729Sjoerg   CGM.addUsedGlobal(CovData);
17367330f729Sjoerg   // Create the deferred function records array
17377330f729Sjoerg   if (!FunctionNames.empty()) {
17387330f729Sjoerg     auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
17397330f729Sjoerg                                            FunctionNames.size());
17407330f729Sjoerg     auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
17417330f729Sjoerg     // This variable will *NOT* be emitted to the object file. It is used
17427330f729Sjoerg     // to pass the list of names referenced to codegen.
17437330f729Sjoerg     new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
17447330f729Sjoerg                              llvm::GlobalValue::InternalLinkage, NamesArrVal,
17457330f729Sjoerg                              llvm::getCoverageUnusedNamesVarName());
17467330f729Sjoerg   }
17477330f729Sjoerg }
17487330f729Sjoerg 
getFileID(const FileEntry * File)17497330f729Sjoerg unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
17507330f729Sjoerg   auto It = FileEntries.find(File);
17517330f729Sjoerg   if (It != FileEntries.end())
17527330f729Sjoerg     return It->second;
1753*e038c9c4Sjoerg   unsigned FileID = FileEntries.size() + 1;
17547330f729Sjoerg   FileEntries.insert(std::make_pair(File, FileID));
17557330f729Sjoerg   return FileID;
17567330f729Sjoerg }
17577330f729Sjoerg 
emitCounterMapping(const Decl * D,llvm::raw_ostream & OS)17587330f729Sjoerg void CoverageMappingGen::emitCounterMapping(const Decl *D,
17597330f729Sjoerg                                             llvm::raw_ostream &OS) {
17607330f729Sjoerg   assert(CounterMap);
17617330f729Sjoerg   CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts);
17627330f729Sjoerg   Walker.VisitDecl(D);
17637330f729Sjoerg   Walker.write(OS);
17647330f729Sjoerg }
17657330f729Sjoerg 
emitEmptyMapping(const Decl * D,llvm::raw_ostream & OS)17667330f729Sjoerg void CoverageMappingGen::emitEmptyMapping(const Decl *D,
17677330f729Sjoerg                                           llvm::raw_ostream &OS) {
17687330f729Sjoerg   EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
17697330f729Sjoerg   Walker.VisitDecl(D);
17707330f729Sjoerg   Walker.write(OS);
17717330f729Sjoerg }
1772