10b57cec5SDimitry Andric //===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Instrumentation-based code coverage mapping generator
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "CoverageMappingGen.h"
140b57cec5SDimitry Andric #include "CodeGenFunction.h"
150b57cec5SDimitry Andric #include "clang/AST/StmtVisitor.h"
165ffd83dbSDimitry Andric #include "clang/Basic/Diagnostic.h"
175ffd83dbSDimitry Andric #include "clang/Basic/FileManager.h"
185ffd83dbSDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h"
190b57cec5SDimitry Andric #include "clang/Lex/Lexer.h"
205ffd83dbSDimitry Andric #include "llvm/ADT/Optional.h"
210b57cec5SDimitry Andric #include "llvm/ADT/SmallSet.h"
220b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
230b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMapping.h"
240b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
250b57cec5SDimitry Andric #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
260b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
270b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
280b57cec5SDimitry Andric #include "llvm/Support/Path.h"
290b57cec5SDimitry Andric 
305ffd83dbSDimitry Andric // This selects the coverage mapping format defined when `InstrProfData.inc`
315ffd83dbSDimitry Andric // is textually included.
325ffd83dbSDimitry Andric #define COVMAP_V3
335ffd83dbSDimitry Andric 
34af732203SDimitry Andric static llvm::cl::opt<bool> EmptyLineCommentCoverage(
35af732203SDimitry Andric     "emptyline-comment-coverage",
36af732203SDimitry Andric     llvm::cl::desc("Emit emptylines and comment lines as skipped regions (only "
37af732203SDimitry Andric                    "disable it on test)"),
38af732203SDimitry Andric     llvm::cl::init(true), llvm::cl::Hidden);
39af732203SDimitry Andric 
400b57cec5SDimitry Andric using namespace clang;
410b57cec5SDimitry Andric using namespace CodeGen;
420b57cec5SDimitry Andric using namespace llvm::coverage;
430b57cec5SDimitry Andric 
44af732203SDimitry Andric CoverageSourceInfo *
setUpCoverageCallbacks(Preprocessor & PP)45af732203SDimitry Andric CoverageMappingModuleGen::setUpCoverageCallbacks(Preprocessor &PP) {
46af732203SDimitry Andric   CoverageSourceInfo *CoverageInfo =
47af732203SDimitry Andric       new CoverageSourceInfo(PP.getSourceManager());
48af732203SDimitry Andric   PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(CoverageInfo));
49af732203SDimitry Andric   if (EmptyLineCommentCoverage) {
50af732203SDimitry Andric     PP.addCommentHandler(CoverageInfo);
51af732203SDimitry Andric     PP.setEmptylineHandler(CoverageInfo);
52af732203SDimitry Andric     PP.setPreprocessToken(true);
53af732203SDimitry Andric     PP.setTokenWatcher([CoverageInfo](clang::Token Tok) {
54af732203SDimitry Andric       // Update previous token location.
55af732203SDimitry Andric       CoverageInfo->PrevTokLoc = Tok.getLocation();
56af732203SDimitry Andric       if (Tok.getKind() != clang::tok::eod)
57af732203SDimitry Andric         CoverageInfo->updateNextTokLoc(Tok.getLocation());
58af732203SDimitry Andric     });
59af732203SDimitry Andric   }
60af732203SDimitry Andric   return CoverageInfo;
61af732203SDimitry Andric }
62af732203SDimitry Andric 
AddSkippedRange(SourceRange Range)63af732203SDimitry Andric void CoverageSourceInfo::AddSkippedRange(SourceRange Range) {
64af732203SDimitry Andric   if (EmptyLineCommentCoverage && !SkippedRanges.empty() &&
65af732203SDimitry Andric       PrevTokLoc == SkippedRanges.back().PrevTokLoc &&
66af732203SDimitry Andric       SourceMgr.isWrittenInSameFile(SkippedRanges.back().Range.getEnd(),
67af732203SDimitry Andric                                     Range.getBegin()))
68af732203SDimitry Andric     SkippedRanges.back().Range.setEnd(Range.getEnd());
69af732203SDimitry Andric   else
70af732203SDimitry Andric     SkippedRanges.push_back({Range, PrevTokLoc});
71af732203SDimitry Andric }
72af732203SDimitry Andric 
SourceRangeSkipped(SourceRange Range,SourceLocation)730b57cec5SDimitry Andric void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range, SourceLocation) {
74af732203SDimitry Andric   AddSkippedRange(Range);
75af732203SDimitry Andric }
76af732203SDimitry Andric 
HandleEmptyline(SourceRange Range)77af732203SDimitry Andric void CoverageSourceInfo::HandleEmptyline(SourceRange Range) {
78af732203SDimitry Andric   AddSkippedRange(Range);
79af732203SDimitry Andric }
80af732203SDimitry Andric 
HandleComment(Preprocessor & PP,SourceRange Range)81af732203SDimitry Andric bool CoverageSourceInfo::HandleComment(Preprocessor &PP, SourceRange Range) {
82af732203SDimitry Andric   AddSkippedRange(Range);
83af732203SDimitry Andric   return false;
84af732203SDimitry Andric }
85af732203SDimitry Andric 
updateNextTokLoc(SourceLocation Loc)86af732203SDimitry Andric void CoverageSourceInfo::updateNextTokLoc(SourceLocation Loc) {
87af732203SDimitry Andric   if (!SkippedRanges.empty() && SkippedRanges.back().NextTokLoc.isInvalid())
88af732203SDimitry Andric     SkippedRanges.back().NextTokLoc = Loc;
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric namespace {
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric /// A region of source code that can be mapped to a counter.
940b57cec5SDimitry Andric class SourceMappingRegion {
95af732203SDimitry Andric   /// Primary Counter that is also used for Branch Regions for "True" branches.
960b57cec5SDimitry Andric   Counter Count;
970b57cec5SDimitry Andric 
98af732203SDimitry Andric   /// Secondary Counter used for Branch Regions for "False" branches.
99af732203SDimitry Andric   Optional<Counter> FalseCount;
100af732203SDimitry Andric 
1010b57cec5SDimitry Andric   /// The region's starting location.
1020b57cec5SDimitry Andric   Optional<SourceLocation> LocStart;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   /// The region's ending location.
1050b57cec5SDimitry Andric   Optional<SourceLocation> LocEnd;
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric   /// Whether this region is a gap region. The count from a gap region is set
1080b57cec5SDimitry Andric   /// as the line execution count if there are no other regions on the line.
1090b57cec5SDimitry Andric   bool GapRegion;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric public:
SourceMappingRegion(Counter Count,Optional<SourceLocation> LocStart,Optional<SourceLocation> LocEnd,bool GapRegion=false)1120b57cec5SDimitry Andric   SourceMappingRegion(Counter Count, Optional<SourceLocation> LocStart,
113*5f7ddb14SDimitry Andric                       Optional<SourceLocation> LocEnd, bool GapRegion = false)
114*5f7ddb14SDimitry Andric       : Count(Count), LocStart(LocStart), LocEnd(LocEnd), GapRegion(GapRegion) {
115*5f7ddb14SDimitry Andric   }
1160b57cec5SDimitry Andric 
SourceMappingRegion(Counter Count,Optional<Counter> FalseCount,Optional<SourceLocation> LocStart,Optional<SourceLocation> LocEnd,bool GapRegion=false)117af732203SDimitry Andric   SourceMappingRegion(Counter Count, Optional<Counter> FalseCount,
118af732203SDimitry Andric                       Optional<SourceLocation> LocStart,
119*5f7ddb14SDimitry Andric                       Optional<SourceLocation> LocEnd, bool GapRegion = false)
120af732203SDimitry Andric       : Count(Count), FalseCount(FalseCount), LocStart(LocStart),
121*5f7ddb14SDimitry Andric         LocEnd(LocEnd), GapRegion(GapRegion) {}
122af732203SDimitry Andric 
getCounter() const1230b57cec5SDimitry Andric   const Counter &getCounter() const { return Count; }
1240b57cec5SDimitry Andric 
getFalseCounter() const125af732203SDimitry Andric   const Counter &getFalseCounter() const {
126af732203SDimitry Andric     assert(FalseCount && "Region has no alternate counter");
127af732203SDimitry Andric     return *FalseCount;
128af732203SDimitry Andric   }
129af732203SDimitry Andric 
setCounter(Counter C)1300b57cec5SDimitry Andric   void setCounter(Counter C) { Count = C; }
1310b57cec5SDimitry Andric 
hasStartLoc() const1320b57cec5SDimitry Andric   bool hasStartLoc() const { return LocStart.hasValue(); }
1330b57cec5SDimitry Andric 
setStartLoc(SourceLocation Loc)1340b57cec5SDimitry Andric   void setStartLoc(SourceLocation Loc) { LocStart = Loc; }
1350b57cec5SDimitry Andric 
getBeginLoc() const1360b57cec5SDimitry Andric   SourceLocation getBeginLoc() const {
1370b57cec5SDimitry Andric     assert(LocStart && "Region has no start location");
1380b57cec5SDimitry Andric     return *LocStart;
1390b57cec5SDimitry Andric   }
1400b57cec5SDimitry Andric 
hasEndLoc() const1410b57cec5SDimitry Andric   bool hasEndLoc() const { return LocEnd.hasValue(); }
1420b57cec5SDimitry Andric 
setEndLoc(SourceLocation Loc)1430b57cec5SDimitry Andric   void setEndLoc(SourceLocation Loc) {
1440b57cec5SDimitry Andric     assert(Loc.isValid() && "Setting an invalid end location");
1450b57cec5SDimitry Andric     LocEnd = Loc;
1460b57cec5SDimitry Andric   }
1470b57cec5SDimitry Andric 
getEndLoc() const1480b57cec5SDimitry Andric   SourceLocation getEndLoc() const {
1490b57cec5SDimitry Andric     assert(LocEnd && "Region has no end location");
1500b57cec5SDimitry Andric     return *LocEnd;
1510b57cec5SDimitry Andric   }
1520b57cec5SDimitry Andric 
isGap() const1530b57cec5SDimitry Andric   bool isGap() const { return GapRegion; }
1540b57cec5SDimitry Andric 
setGap(bool Gap)1550b57cec5SDimitry Andric   void setGap(bool Gap) { GapRegion = Gap; }
156af732203SDimitry Andric 
isBranch() const157af732203SDimitry Andric   bool isBranch() const { return FalseCount.hasValue(); }
1580b57cec5SDimitry Andric };
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric /// Spelling locations for the start and end of a source region.
1610b57cec5SDimitry Andric struct SpellingRegion {
1620b57cec5SDimitry Andric   /// The line where the region starts.
1630b57cec5SDimitry Andric   unsigned LineStart;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   /// The column where the region starts.
1660b57cec5SDimitry Andric   unsigned ColumnStart;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   /// The line where the region ends.
1690b57cec5SDimitry Andric   unsigned LineEnd;
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric   /// The column where the region ends.
1720b57cec5SDimitry Andric   unsigned ColumnEnd;
1730b57cec5SDimitry Andric 
SpellingRegion__anone2f8b4240211::SpellingRegion1740b57cec5SDimitry Andric   SpellingRegion(SourceManager &SM, SourceLocation LocStart,
1750b57cec5SDimitry Andric                  SourceLocation LocEnd) {
1760b57cec5SDimitry Andric     LineStart = SM.getSpellingLineNumber(LocStart);
1770b57cec5SDimitry Andric     ColumnStart = SM.getSpellingColumnNumber(LocStart);
1780b57cec5SDimitry Andric     LineEnd = SM.getSpellingLineNumber(LocEnd);
1790b57cec5SDimitry Andric     ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
SpellingRegion__anone2f8b4240211::SpellingRegion1820b57cec5SDimitry Andric   SpellingRegion(SourceManager &SM, SourceMappingRegion &R)
1830b57cec5SDimitry Andric       : SpellingRegion(SM, R.getBeginLoc(), R.getEndLoc()) {}
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   /// Check if the start and end locations appear in source order, i.e
1860b57cec5SDimitry Andric   /// top->bottom, left->right.
isInSourceOrder__anone2f8b4240211::SpellingRegion1870b57cec5SDimitry Andric   bool isInSourceOrder() const {
1880b57cec5SDimitry Andric     return (LineStart < LineEnd) ||
1890b57cec5SDimitry Andric            (LineStart == LineEnd && ColumnStart <= ColumnEnd);
1900b57cec5SDimitry Andric   }
1910b57cec5SDimitry Andric };
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric /// Provides the common functionality for the different
1940b57cec5SDimitry Andric /// coverage mapping region builders.
1950b57cec5SDimitry Andric class CoverageMappingBuilder {
1960b57cec5SDimitry Andric public:
1970b57cec5SDimitry Andric   CoverageMappingModuleGen &CVM;
1980b57cec5SDimitry Andric   SourceManager &SM;
1990b57cec5SDimitry Andric   const LangOptions &LangOpts;
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric private:
2020b57cec5SDimitry Andric   /// Map of clang's FileIDs to IDs used for coverage mapping.
2030b57cec5SDimitry Andric   llvm::SmallDenseMap<FileID, std::pair<unsigned, SourceLocation>, 8>
2040b57cec5SDimitry Andric       FileIDMapping;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric public:
2070b57cec5SDimitry Andric   /// The coverage mapping regions for this function
2080b57cec5SDimitry Andric   llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
2090b57cec5SDimitry Andric   /// The source mapping regions for this function.
2100b57cec5SDimitry Andric   std::vector<SourceMappingRegion> SourceRegions;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric   /// A set of regions which can be used as a filter.
2130b57cec5SDimitry Andric   ///
2140b57cec5SDimitry Andric   /// It is produced by emitExpansionRegions() and is used in
2150b57cec5SDimitry Andric   /// emitSourceRegions() to suppress producing code regions if
2160b57cec5SDimitry Andric   /// the same area is covered by expansion regions.
2170b57cec5SDimitry Andric   typedef llvm::SmallSet<std::pair<SourceLocation, SourceLocation>, 8>
2180b57cec5SDimitry Andric       SourceRegionFilter;
2190b57cec5SDimitry Andric 
CoverageMappingBuilder(CoverageMappingModuleGen & CVM,SourceManager & SM,const LangOptions & LangOpts)2200b57cec5SDimitry Andric   CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
2210b57cec5SDimitry Andric                          const LangOptions &LangOpts)
2220b57cec5SDimitry Andric       : CVM(CVM), SM(SM), LangOpts(LangOpts) {}
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   /// Return the precise end location for the given token.
getPreciseTokenLocEnd(SourceLocation Loc)2250b57cec5SDimitry Andric   SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
2260b57cec5SDimitry Andric     // We avoid getLocForEndOfToken here, because it doesn't do what we want for
2270b57cec5SDimitry Andric     // macro locations, which we just treat as expanded files.
2280b57cec5SDimitry Andric     unsigned TokLen =
2290b57cec5SDimitry Andric         Lexer::MeasureTokenLength(SM.getSpellingLoc(Loc), SM, LangOpts);
2300b57cec5SDimitry Andric     return Loc.getLocWithOffset(TokLen);
2310b57cec5SDimitry Andric   }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   /// Return the start location of an included file or expanded macro.
getStartOfFileOrMacro(SourceLocation Loc)2340b57cec5SDimitry Andric   SourceLocation getStartOfFileOrMacro(SourceLocation Loc) {
2350b57cec5SDimitry Andric     if (Loc.isMacroID())
2360b57cec5SDimitry Andric       return Loc.getLocWithOffset(-SM.getFileOffset(Loc));
2370b57cec5SDimitry Andric     return SM.getLocForStartOfFile(SM.getFileID(Loc));
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   /// Return the end location of an included file or expanded macro.
getEndOfFileOrMacro(SourceLocation Loc)2410b57cec5SDimitry Andric   SourceLocation getEndOfFileOrMacro(SourceLocation Loc) {
2420b57cec5SDimitry Andric     if (Loc.isMacroID())
2430b57cec5SDimitry Andric       return Loc.getLocWithOffset(SM.getFileIDSize(SM.getFileID(Loc)) -
2440b57cec5SDimitry Andric                                   SM.getFileOffset(Loc));
2450b57cec5SDimitry Andric     return SM.getLocForEndOfFile(SM.getFileID(Loc));
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   /// Find out where the current file is included or macro is expanded.
getIncludeOrExpansionLoc(SourceLocation Loc)2490b57cec5SDimitry Andric   SourceLocation getIncludeOrExpansionLoc(SourceLocation Loc) {
2500b57cec5SDimitry Andric     return Loc.isMacroID() ? SM.getImmediateExpansionRange(Loc).getBegin()
2510b57cec5SDimitry Andric                            : SM.getIncludeLoc(SM.getFileID(Loc));
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   /// Return true if \c Loc is a location in a built-in macro.
isInBuiltin(SourceLocation Loc)2550b57cec5SDimitry Andric   bool isInBuiltin(SourceLocation Loc) {
2560b57cec5SDimitry Andric     return SM.getBufferName(SM.getSpellingLoc(Loc)) == "<built-in>";
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   /// Check whether \c Loc is included or expanded from \c Parent.
isNestedIn(SourceLocation Loc,FileID Parent)2600b57cec5SDimitry Andric   bool isNestedIn(SourceLocation Loc, FileID Parent) {
2610b57cec5SDimitry Andric     do {
2620b57cec5SDimitry Andric       Loc = getIncludeOrExpansionLoc(Loc);
2630b57cec5SDimitry Andric       if (Loc.isInvalid())
2640b57cec5SDimitry Andric         return false;
2650b57cec5SDimitry Andric     } while (!SM.isInFileID(Loc, Parent));
2660b57cec5SDimitry Andric     return true;
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   /// Get the start of \c S ignoring macro arguments and builtin macros.
getStart(const Stmt * S)2700b57cec5SDimitry Andric   SourceLocation getStart(const Stmt *S) {
2710b57cec5SDimitry Andric     SourceLocation Loc = S->getBeginLoc();
2720b57cec5SDimitry Andric     while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
2730b57cec5SDimitry Andric       Loc = SM.getImmediateExpansionRange(Loc).getBegin();
2740b57cec5SDimitry Andric     return Loc;
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   /// Get the end of \c S ignoring macro arguments and builtin macros.
getEnd(const Stmt * S)2780b57cec5SDimitry Andric   SourceLocation getEnd(const Stmt *S) {
2790b57cec5SDimitry Andric     SourceLocation Loc = S->getEndLoc();
2800b57cec5SDimitry Andric     while (SM.isMacroArgExpansion(Loc) || isInBuiltin(Loc))
2810b57cec5SDimitry Andric       Loc = SM.getImmediateExpansionRange(Loc).getBegin();
2820b57cec5SDimitry Andric     return getPreciseTokenLocEnd(Loc);
2830b57cec5SDimitry Andric   }
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   /// Find the set of files we have regions for and assign IDs
2860b57cec5SDimitry Andric   ///
2870b57cec5SDimitry Andric   /// Fills \c Mapping with the virtual file mapping needed to write out
2880b57cec5SDimitry Andric   /// coverage and collects the necessary file information to emit source and
2890b57cec5SDimitry Andric   /// expansion regions.
gatherFileIDs(SmallVectorImpl<unsigned> & Mapping)2900b57cec5SDimitry Andric   void gatherFileIDs(SmallVectorImpl<unsigned> &Mapping) {
2910b57cec5SDimitry Andric     FileIDMapping.clear();
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric     llvm::SmallSet<FileID, 8> Visited;
2940b57cec5SDimitry Andric     SmallVector<std::pair<SourceLocation, unsigned>, 8> FileLocs;
2950b57cec5SDimitry Andric     for (const auto &Region : SourceRegions) {
2960b57cec5SDimitry Andric       SourceLocation Loc = Region.getBeginLoc();
2970b57cec5SDimitry Andric       FileID File = SM.getFileID(Loc);
2980b57cec5SDimitry Andric       if (!Visited.insert(File).second)
2990b57cec5SDimitry Andric         continue;
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric       // Do not map FileID's associated with system headers.
3020b57cec5SDimitry Andric       if (SM.isInSystemHeader(SM.getSpellingLoc(Loc)))
3030b57cec5SDimitry Andric         continue;
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric       unsigned Depth = 0;
3060b57cec5SDimitry Andric       for (SourceLocation Parent = getIncludeOrExpansionLoc(Loc);
3070b57cec5SDimitry Andric            Parent.isValid(); Parent = getIncludeOrExpansionLoc(Parent))
3080b57cec5SDimitry Andric         ++Depth;
3090b57cec5SDimitry Andric       FileLocs.push_back(std::make_pair(Loc, Depth));
3100b57cec5SDimitry Andric     }
3110b57cec5SDimitry Andric     llvm::stable_sort(FileLocs, llvm::less_second());
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     for (const auto &FL : FileLocs) {
3140b57cec5SDimitry Andric       SourceLocation Loc = FL.first;
3150b57cec5SDimitry Andric       FileID SpellingFile = SM.getDecomposedSpellingLoc(Loc).first;
3160b57cec5SDimitry Andric       auto Entry = SM.getFileEntryForID(SpellingFile);
3170b57cec5SDimitry Andric       if (!Entry)
3180b57cec5SDimitry Andric         continue;
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric       FileIDMapping[SM.getFileID(Loc)] = std::make_pair(Mapping.size(), Loc);
3210b57cec5SDimitry Andric       Mapping.push_back(CVM.getFileID(Entry));
3220b57cec5SDimitry Andric     }
3230b57cec5SDimitry Andric   }
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   /// Get the coverage mapping file ID for \c Loc.
3260b57cec5SDimitry Andric   ///
3270b57cec5SDimitry Andric   /// If such file id doesn't exist, return None.
getCoverageFileID(SourceLocation Loc)3280b57cec5SDimitry Andric   Optional<unsigned> getCoverageFileID(SourceLocation Loc) {
3290b57cec5SDimitry Andric     auto Mapping = FileIDMapping.find(SM.getFileID(Loc));
3300b57cec5SDimitry Andric     if (Mapping != FileIDMapping.end())
3310b57cec5SDimitry Andric       return Mapping->second.first;
3320b57cec5SDimitry Andric     return None;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
335af732203SDimitry Andric   /// This shrinks the skipped range if it spans a line that contains a
336af732203SDimitry Andric   /// non-comment token. If shrinking the skipped range would make it empty,
337af732203SDimitry Andric   /// this returns None.
adjustSkippedRange(SourceManager & SM,SourceLocation LocStart,SourceLocation LocEnd,SourceLocation PrevTokLoc,SourceLocation NextTokLoc)338af732203SDimitry Andric   Optional<SpellingRegion> adjustSkippedRange(SourceManager &SM,
339af732203SDimitry Andric                                               SourceLocation LocStart,
340af732203SDimitry Andric                                               SourceLocation LocEnd,
341af732203SDimitry Andric                                               SourceLocation PrevTokLoc,
342af732203SDimitry Andric                                               SourceLocation NextTokLoc) {
343af732203SDimitry Andric     SpellingRegion SR{SM, LocStart, LocEnd};
344af732203SDimitry Andric     SR.ColumnStart = 1;
345af732203SDimitry Andric     if (PrevTokLoc.isValid() && SM.isWrittenInSameFile(LocStart, PrevTokLoc) &&
346af732203SDimitry Andric         SR.LineStart == SM.getSpellingLineNumber(PrevTokLoc))
347af732203SDimitry Andric       SR.LineStart++;
348af732203SDimitry Andric     if (NextTokLoc.isValid() && SM.isWrittenInSameFile(LocEnd, NextTokLoc) &&
349af732203SDimitry Andric         SR.LineEnd == SM.getSpellingLineNumber(NextTokLoc)) {
350af732203SDimitry Andric       SR.LineEnd--;
351af732203SDimitry Andric       SR.ColumnEnd++;
352af732203SDimitry Andric     }
353af732203SDimitry Andric     if (SR.isInSourceOrder())
354af732203SDimitry Andric       return SR;
355af732203SDimitry Andric     return None;
356af732203SDimitry Andric   }
357af732203SDimitry Andric 
3580b57cec5SDimitry Andric   /// Gather all the regions that were skipped by the preprocessor
359af732203SDimitry Andric   /// using the constructs like #if or comments.
gatherSkippedRegions()3600b57cec5SDimitry Andric   void gatherSkippedRegions() {
3610b57cec5SDimitry Andric     /// An array of the minimum lineStarts and the maximum lineEnds
3620b57cec5SDimitry Andric     /// for mapping regions from the appropriate source files.
3630b57cec5SDimitry Andric     llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
3640b57cec5SDimitry Andric     FileLineRanges.resize(
3650b57cec5SDimitry Andric         FileIDMapping.size(),
3660b57cec5SDimitry Andric         std::make_pair(std::numeric_limits<unsigned>::max(), 0));
3670b57cec5SDimitry Andric     for (const auto &R : MappingRegions) {
3680b57cec5SDimitry Andric       FileLineRanges[R.FileID].first =
3690b57cec5SDimitry Andric           std::min(FileLineRanges[R.FileID].first, R.LineStart);
3700b57cec5SDimitry Andric       FileLineRanges[R.FileID].second =
3710b57cec5SDimitry Andric           std::max(FileLineRanges[R.FileID].second, R.LineEnd);
3720b57cec5SDimitry Andric     }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric     auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
375af732203SDimitry Andric     for (auto &I : SkippedRanges) {
376af732203SDimitry Andric       SourceRange Range = I.Range;
377af732203SDimitry Andric       auto LocStart = Range.getBegin();
378af732203SDimitry Andric       auto LocEnd = Range.getEnd();
3790b57cec5SDimitry Andric       assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
3800b57cec5SDimitry Andric              "region spans multiple files");
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric       auto CovFileID = getCoverageFileID(LocStart);
3830b57cec5SDimitry Andric       if (!CovFileID)
3840b57cec5SDimitry Andric         continue;
385af732203SDimitry Andric       Optional<SpellingRegion> SR =
386af732203SDimitry Andric           adjustSkippedRange(SM, LocStart, LocEnd, I.PrevTokLoc, I.NextTokLoc);
387af732203SDimitry Andric       if (!SR.hasValue())
388af732203SDimitry Andric         continue;
3890b57cec5SDimitry Andric       auto Region = CounterMappingRegion::makeSkipped(
390af732203SDimitry Andric           *CovFileID, SR->LineStart, SR->ColumnStart, SR->LineEnd,
391af732203SDimitry Andric           SR->ColumnEnd);
3920b57cec5SDimitry Andric       // Make sure that we only collect the regions that are inside
3930b57cec5SDimitry Andric       // the source code of this function.
3940b57cec5SDimitry Andric       if (Region.LineStart >= FileLineRanges[*CovFileID].first &&
3950b57cec5SDimitry Andric           Region.LineEnd <= FileLineRanges[*CovFileID].second)
3960b57cec5SDimitry Andric         MappingRegions.push_back(Region);
3970b57cec5SDimitry Andric     }
3980b57cec5SDimitry Andric   }
3990b57cec5SDimitry Andric 
4000b57cec5SDimitry Andric   /// Generate the coverage counter mapping regions from collected
4010b57cec5SDimitry Andric   /// source regions.
emitSourceRegions(const SourceRegionFilter & Filter)4020b57cec5SDimitry Andric   void emitSourceRegions(const SourceRegionFilter &Filter) {
4030b57cec5SDimitry Andric     for (const auto &Region : SourceRegions) {
4040b57cec5SDimitry Andric       assert(Region.hasEndLoc() && "incomplete region");
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric       SourceLocation LocStart = Region.getBeginLoc();
4070b57cec5SDimitry Andric       assert(SM.getFileID(LocStart).isValid() && "region in invalid file");
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric       // Ignore regions from system headers.
4100b57cec5SDimitry Andric       if (SM.isInSystemHeader(SM.getSpellingLoc(LocStart)))
4110b57cec5SDimitry Andric         continue;
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric       auto CovFileID = getCoverageFileID(LocStart);
4140b57cec5SDimitry Andric       // Ignore regions that don't have a file, such as builtin macros.
4150b57cec5SDimitry Andric       if (!CovFileID)
4160b57cec5SDimitry Andric         continue;
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric       SourceLocation LocEnd = Region.getEndLoc();
4190b57cec5SDimitry Andric       assert(SM.isWrittenInSameFile(LocStart, LocEnd) &&
4200b57cec5SDimitry Andric              "region spans multiple files");
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric       // Don't add code regions for the area covered by expansion regions.
4230b57cec5SDimitry Andric       // This not only suppresses redundant regions, but sometimes prevents
4240b57cec5SDimitry Andric       // creating regions with wrong counters if, for example, a statement's
4250b57cec5SDimitry Andric       // body ends at the end of a nested macro.
4260b57cec5SDimitry Andric       if (Filter.count(std::make_pair(LocStart, LocEnd)))
4270b57cec5SDimitry Andric         continue;
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric       // Find the spelling locations for the mapping region.
4300b57cec5SDimitry Andric       SpellingRegion SR{SM, LocStart, LocEnd};
4310b57cec5SDimitry Andric       assert(SR.isInSourceOrder() && "region start and end out of order");
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric       if (Region.isGap()) {
4340b57cec5SDimitry Andric         MappingRegions.push_back(CounterMappingRegion::makeGapRegion(
4350b57cec5SDimitry Andric             Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
4360b57cec5SDimitry Andric             SR.LineEnd, SR.ColumnEnd));
437af732203SDimitry Andric       } else if (Region.isBranch()) {
438af732203SDimitry Andric         MappingRegions.push_back(CounterMappingRegion::makeBranchRegion(
439af732203SDimitry Andric             Region.getCounter(), Region.getFalseCounter(), *CovFileID,
440af732203SDimitry Andric             SR.LineStart, SR.ColumnStart, SR.LineEnd, SR.ColumnEnd));
4410b57cec5SDimitry Andric       } else {
4420b57cec5SDimitry Andric         MappingRegions.push_back(CounterMappingRegion::makeRegion(
4430b57cec5SDimitry Andric             Region.getCounter(), *CovFileID, SR.LineStart, SR.ColumnStart,
4440b57cec5SDimitry Andric             SR.LineEnd, SR.ColumnEnd));
4450b57cec5SDimitry Andric       }
4460b57cec5SDimitry Andric     }
4470b57cec5SDimitry Andric   }
4480b57cec5SDimitry Andric 
4490b57cec5SDimitry Andric   /// Generate expansion regions for each virtual file we've seen.
emitExpansionRegions()4500b57cec5SDimitry Andric   SourceRegionFilter emitExpansionRegions() {
4510b57cec5SDimitry Andric     SourceRegionFilter Filter;
4520b57cec5SDimitry Andric     for (const auto &FM : FileIDMapping) {
4530b57cec5SDimitry Andric       SourceLocation ExpandedLoc = FM.second.second;
4540b57cec5SDimitry Andric       SourceLocation ParentLoc = getIncludeOrExpansionLoc(ExpandedLoc);
4550b57cec5SDimitry Andric       if (ParentLoc.isInvalid())
4560b57cec5SDimitry Andric         continue;
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric       auto ParentFileID = getCoverageFileID(ParentLoc);
4590b57cec5SDimitry Andric       if (!ParentFileID)
4600b57cec5SDimitry Andric         continue;
4610b57cec5SDimitry Andric       auto ExpandedFileID = getCoverageFileID(ExpandedLoc);
4620b57cec5SDimitry Andric       assert(ExpandedFileID && "expansion in uncovered file");
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric       SourceLocation LocEnd = getPreciseTokenLocEnd(ParentLoc);
4650b57cec5SDimitry Andric       assert(SM.isWrittenInSameFile(ParentLoc, LocEnd) &&
4660b57cec5SDimitry Andric              "region spans multiple files");
4670b57cec5SDimitry Andric       Filter.insert(std::make_pair(ParentLoc, LocEnd));
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric       SpellingRegion SR{SM, ParentLoc, LocEnd};
4700b57cec5SDimitry Andric       assert(SR.isInSourceOrder() && "region start and end out of order");
4710b57cec5SDimitry Andric       MappingRegions.push_back(CounterMappingRegion::makeExpansion(
4720b57cec5SDimitry Andric           *ParentFileID, *ExpandedFileID, SR.LineStart, SR.ColumnStart,
4730b57cec5SDimitry Andric           SR.LineEnd, SR.ColumnEnd));
4740b57cec5SDimitry Andric     }
4750b57cec5SDimitry Andric     return Filter;
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric };
4780b57cec5SDimitry Andric 
4790b57cec5SDimitry Andric /// Creates unreachable coverage regions for the functions that
4800b57cec5SDimitry Andric /// are not emitted.
4810b57cec5SDimitry Andric struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
EmptyCoverageMappingBuilder__anone2f8b4240211::EmptyCoverageMappingBuilder4820b57cec5SDimitry Andric   EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
4830b57cec5SDimitry Andric                               const LangOptions &LangOpts)
4840b57cec5SDimitry Andric       : CoverageMappingBuilder(CVM, SM, LangOpts) {}
4850b57cec5SDimitry Andric 
VisitDecl__anone2f8b4240211::EmptyCoverageMappingBuilder4860b57cec5SDimitry Andric   void VisitDecl(const Decl *D) {
4870b57cec5SDimitry Andric     if (!D->hasBody())
4880b57cec5SDimitry Andric       return;
4890b57cec5SDimitry Andric     auto Body = D->getBody();
4900b57cec5SDimitry Andric     SourceLocation Start = getStart(Body);
4910b57cec5SDimitry Andric     SourceLocation End = getEnd(Body);
4920b57cec5SDimitry Andric     if (!SM.isWrittenInSameFile(Start, End)) {
4930b57cec5SDimitry Andric       // Walk up to find the common ancestor.
4940b57cec5SDimitry Andric       // Correct the locations accordingly.
4950b57cec5SDimitry Andric       FileID StartFileID = SM.getFileID(Start);
4960b57cec5SDimitry Andric       FileID EndFileID = SM.getFileID(End);
4970b57cec5SDimitry Andric       while (StartFileID != EndFileID && !isNestedIn(End, StartFileID)) {
4980b57cec5SDimitry Andric         Start = getIncludeOrExpansionLoc(Start);
4990b57cec5SDimitry Andric         assert(Start.isValid() &&
5000b57cec5SDimitry Andric                "Declaration start location not nested within a known region");
5010b57cec5SDimitry Andric         StartFileID = SM.getFileID(Start);
5020b57cec5SDimitry Andric       }
5030b57cec5SDimitry Andric       while (StartFileID != EndFileID) {
5040b57cec5SDimitry Andric         End = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(End));
5050b57cec5SDimitry Andric         assert(End.isValid() &&
5060b57cec5SDimitry Andric                "Declaration end location not nested within a known region");
5070b57cec5SDimitry Andric         EndFileID = SM.getFileID(End);
5080b57cec5SDimitry Andric       }
5090b57cec5SDimitry Andric     }
5100b57cec5SDimitry Andric     SourceRegions.emplace_back(Counter(), Start, End);
5110b57cec5SDimitry Andric   }
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   /// Write the mapping data to the output stream
write__anone2f8b4240211::EmptyCoverageMappingBuilder5140b57cec5SDimitry Andric   void write(llvm::raw_ostream &OS) {
5150b57cec5SDimitry Andric     SmallVector<unsigned, 16> FileIDMapping;
5160b57cec5SDimitry Andric     gatherFileIDs(FileIDMapping);
5170b57cec5SDimitry Andric     emitSourceRegions(SourceRegionFilter());
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric     if (MappingRegions.empty())
5200b57cec5SDimitry Andric       return;
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric     CoverageMappingWriter Writer(FileIDMapping, None, MappingRegions);
5230b57cec5SDimitry Andric     Writer.write(OS);
5240b57cec5SDimitry Andric   }
5250b57cec5SDimitry Andric };
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric /// A StmtVisitor that creates coverage mapping regions which map
5280b57cec5SDimitry Andric /// from the source code locations to the PGO counters.
5290b57cec5SDimitry Andric struct CounterCoverageMappingBuilder
5300b57cec5SDimitry Andric     : public CoverageMappingBuilder,
5310b57cec5SDimitry Andric       public ConstStmtVisitor<CounterCoverageMappingBuilder> {
5320b57cec5SDimitry Andric   /// The map of statements to count values.
5330b57cec5SDimitry Andric   llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   /// A stack of currently live regions.
5360b57cec5SDimitry Andric   std::vector<SourceMappingRegion> RegionStack;
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric   CounterExpressionBuilder Builder;
5390b57cec5SDimitry Andric 
5400b57cec5SDimitry Andric   /// A location in the most recently visited file or macro.
5410b57cec5SDimitry Andric   ///
5420b57cec5SDimitry Andric   /// This is used to adjust the active source regions appropriately when
5430b57cec5SDimitry Andric   /// expressions cross file or macro boundaries.
5440b57cec5SDimitry Andric   SourceLocation MostRecentLocation;
5450b57cec5SDimitry Andric 
546*5f7ddb14SDimitry Andric   /// Whether the visitor at a terminate statement.
547*5f7ddb14SDimitry Andric   bool HasTerminateStmt = false;
548*5f7ddb14SDimitry Andric 
549*5f7ddb14SDimitry Andric   /// Gap region counter after terminate statement.
550*5f7ddb14SDimitry Andric   Counter GapRegionCounter;
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   /// Return a counter for the subtraction of \c RHS from \c LHS
subtractCounters__anone2f8b4240211::CounterCoverageMappingBuilder5530b57cec5SDimitry Andric   Counter subtractCounters(Counter LHS, Counter RHS) {
5540b57cec5SDimitry Andric     return Builder.subtract(LHS, RHS);
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   /// Return a counter for the sum of \c LHS and \c RHS.
addCounters__anone2f8b4240211::CounterCoverageMappingBuilder5580b57cec5SDimitry Andric   Counter addCounters(Counter LHS, Counter RHS) {
5590b57cec5SDimitry Andric     return Builder.add(LHS, RHS);
5600b57cec5SDimitry Andric   }
5610b57cec5SDimitry Andric 
addCounters__anone2f8b4240211::CounterCoverageMappingBuilder5620b57cec5SDimitry Andric   Counter addCounters(Counter C1, Counter C2, Counter C3) {
5630b57cec5SDimitry Andric     return addCounters(addCounters(C1, C2), C3);
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric 
5660b57cec5SDimitry Andric   /// Return the region counter for the given statement.
5670b57cec5SDimitry Andric   ///
5680b57cec5SDimitry Andric   /// This should only be called on statements that have a dedicated counter.
getRegionCounter__anone2f8b4240211::CounterCoverageMappingBuilder5690b57cec5SDimitry Andric   Counter getRegionCounter(const Stmt *S) {
5700b57cec5SDimitry Andric     return Counter::getCounter(CounterMap[S]);
5710b57cec5SDimitry Andric   }
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   /// Push a region onto the stack.
5740b57cec5SDimitry Andric   ///
5750b57cec5SDimitry Andric   /// Returns the index on the stack where the region was pushed. This can be
5760b57cec5SDimitry Andric   /// used with popRegions to exit a "scope", ending the region that was pushed.
pushRegion__anone2f8b4240211::CounterCoverageMappingBuilder5770b57cec5SDimitry Andric   size_t pushRegion(Counter Count, Optional<SourceLocation> StartLoc = None,
578af732203SDimitry Andric                     Optional<SourceLocation> EndLoc = None,
579af732203SDimitry Andric                     Optional<Counter> FalseCount = None) {
580af732203SDimitry Andric 
581af732203SDimitry Andric     if (StartLoc && !FalseCount.hasValue()) {
5820b57cec5SDimitry Andric       MostRecentLocation = *StartLoc;
5830b57cec5SDimitry Andric     }
584af732203SDimitry Andric 
585*5f7ddb14SDimitry Andric     RegionStack.emplace_back(Count, FalseCount, StartLoc, EndLoc);
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric     return RegionStack.size() - 1;
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric 
locationDepth__anone2f8b4240211::CounterCoverageMappingBuilder5900b57cec5SDimitry Andric   size_t locationDepth(SourceLocation Loc) {
5910b57cec5SDimitry Andric     size_t Depth = 0;
5920b57cec5SDimitry Andric     while (Loc.isValid()) {
5930b57cec5SDimitry Andric       Loc = getIncludeOrExpansionLoc(Loc);
5940b57cec5SDimitry Andric       Depth++;
5950b57cec5SDimitry Andric     }
5960b57cec5SDimitry Andric     return Depth;
5970b57cec5SDimitry Andric   }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   /// Pop regions from the stack into the function's list of regions.
6000b57cec5SDimitry Andric   ///
6010b57cec5SDimitry Andric   /// Adds all regions from \c ParentIndex to the top of the stack to the
6020b57cec5SDimitry Andric   /// function's \c SourceRegions.
popRegions__anone2f8b4240211::CounterCoverageMappingBuilder6030b57cec5SDimitry Andric   void popRegions(size_t ParentIndex) {
6040b57cec5SDimitry Andric     assert(RegionStack.size() >= ParentIndex && "parent not in stack");
6050b57cec5SDimitry Andric     while (RegionStack.size() > ParentIndex) {
6060b57cec5SDimitry Andric       SourceMappingRegion &Region = RegionStack.back();
6070b57cec5SDimitry Andric       if (Region.hasStartLoc()) {
6080b57cec5SDimitry Andric         SourceLocation StartLoc = Region.getBeginLoc();
6090b57cec5SDimitry Andric         SourceLocation EndLoc = Region.hasEndLoc()
6100b57cec5SDimitry Andric                                     ? Region.getEndLoc()
6110b57cec5SDimitry Andric                                     : RegionStack[ParentIndex].getEndLoc();
612af732203SDimitry Andric         bool isBranch = Region.isBranch();
6130b57cec5SDimitry Andric         size_t StartDepth = locationDepth(StartLoc);
6140b57cec5SDimitry Andric         size_t EndDepth = locationDepth(EndLoc);
6150b57cec5SDimitry Andric         while (!SM.isWrittenInSameFile(StartLoc, EndLoc)) {
6160b57cec5SDimitry Andric           bool UnnestStart = StartDepth >= EndDepth;
6170b57cec5SDimitry Andric           bool UnnestEnd = EndDepth >= StartDepth;
6180b57cec5SDimitry Andric           if (UnnestEnd) {
619af732203SDimitry Andric             // The region ends in a nested file or macro expansion. If the
620af732203SDimitry Andric             // region is not a branch region, create a separate region for each
621af732203SDimitry Andric             // expansion, and for all regions, update the EndLoc. Branch
622af732203SDimitry Andric             // regions should not be split in order to keep a straightforward
623af732203SDimitry Andric             // correspondance between the region and its associated branch
624af732203SDimitry Andric             // condition, even if the condition spans multiple depths.
6250b57cec5SDimitry Andric             SourceLocation NestedLoc = getStartOfFileOrMacro(EndLoc);
6260b57cec5SDimitry Andric             assert(SM.isWrittenInSameFile(NestedLoc, EndLoc));
6270b57cec5SDimitry Andric 
628af732203SDimitry Andric             if (!isBranch && !isRegionAlreadyAdded(NestedLoc, EndLoc))
629af732203SDimitry Andric               SourceRegions.emplace_back(Region.getCounter(), NestedLoc,
630af732203SDimitry Andric                                          EndLoc);
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric             EndLoc = getPreciseTokenLocEnd(getIncludeOrExpansionLoc(EndLoc));
6330b57cec5SDimitry Andric             if (EndLoc.isInvalid())
634af732203SDimitry Andric               llvm::report_fatal_error(
635af732203SDimitry Andric                   "File exit not handled before popRegions");
6360b57cec5SDimitry Andric             EndDepth--;
6370b57cec5SDimitry Andric           }
6380b57cec5SDimitry Andric           if (UnnestStart) {
639af732203SDimitry Andric             // The region ends in a nested file or macro expansion. If the
640af732203SDimitry Andric             // region is not a branch region, create a separate region for each
641af732203SDimitry Andric             // expansion, and for all regions, update the StartLoc. Branch
642af732203SDimitry Andric             // regions should not be split in order to keep a straightforward
643af732203SDimitry Andric             // correspondance between the region and its associated branch
644af732203SDimitry Andric             // condition, even if the condition spans multiple depths.
6450b57cec5SDimitry Andric             SourceLocation NestedLoc = getEndOfFileOrMacro(StartLoc);
6460b57cec5SDimitry Andric             assert(SM.isWrittenInSameFile(StartLoc, NestedLoc));
6470b57cec5SDimitry Andric 
648af732203SDimitry Andric             if (!isBranch && !isRegionAlreadyAdded(StartLoc, NestedLoc))
649af732203SDimitry Andric               SourceRegions.emplace_back(Region.getCounter(), StartLoc,
650af732203SDimitry Andric                                          NestedLoc);
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric             StartLoc = getIncludeOrExpansionLoc(StartLoc);
6530b57cec5SDimitry Andric             if (StartLoc.isInvalid())
654af732203SDimitry Andric               llvm::report_fatal_error(
655af732203SDimitry Andric                   "File exit not handled before popRegions");
6560b57cec5SDimitry Andric             StartDepth--;
6570b57cec5SDimitry Andric           }
6580b57cec5SDimitry Andric         }
6590b57cec5SDimitry Andric         Region.setStartLoc(StartLoc);
6600b57cec5SDimitry Andric         Region.setEndLoc(EndLoc);
6610b57cec5SDimitry Andric 
662af732203SDimitry Andric         if (!isBranch) {
6630b57cec5SDimitry Andric           MostRecentLocation = EndLoc;
664af732203SDimitry Andric           // If this region happens to span an entire expansion, we need to
665af732203SDimitry Andric           // make sure we don't overlap the parent region with it.
6660b57cec5SDimitry Andric           if (StartLoc == getStartOfFileOrMacro(StartLoc) &&
6670b57cec5SDimitry Andric               EndLoc == getEndOfFileOrMacro(EndLoc))
6680b57cec5SDimitry Andric             MostRecentLocation = getIncludeOrExpansionLoc(EndLoc);
669af732203SDimitry Andric         }
6700b57cec5SDimitry Andric 
6710b57cec5SDimitry Andric         assert(SM.isWrittenInSameFile(Region.getBeginLoc(), EndLoc));
6720b57cec5SDimitry Andric         assert(SpellingRegion(SM, Region).isInSourceOrder());
6730b57cec5SDimitry Andric         SourceRegions.push_back(Region);
6740b57cec5SDimitry Andric         }
6750b57cec5SDimitry Andric       RegionStack.pop_back();
6760b57cec5SDimitry Andric     }
6770b57cec5SDimitry Andric   }
6780b57cec5SDimitry Andric 
6790b57cec5SDimitry Andric   /// Return the currently active region.
getRegion__anone2f8b4240211::CounterCoverageMappingBuilder6800b57cec5SDimitry Andric   SourceMappingRegion &getRegion() {
6810b57cec5SDimitry Andric     assert(!RegionStack.empty() && "statement has no region");
6820b57cec5SDimitry Andric     return RegionStack.back();
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric   /// Propagate counts through the children of \p S if \p VisitChildren is true.
6860b57cec5SDimitry Andric   /// Otherwise, only emit a count for \p S itself.
propagateCounts__anone2f8b4240211::CounterCoverageMappingBuilder6870b57cec5SDimitry Andric   Counter propagateCounts(Counter TopCount, const Stmt *S,
6880b57cec5SDimitry Andric                           bool VisitChildren = true) {
6890b57cec5SDimitry Andric     SourceLocation StartLoc = getStart(S);
6900b57cec5SDimitry Andric     SourceLocation EndLoc = getEnd(S);
6910b57cec5SDimitry Andric     size_t Index = pushRegion(TopCount, StartLoc, EndLoc);
6920b57cec5SDimitry Andric     if (VisitChildren)
6930b57cec5SDimitry Andric       Visit(S);
6940b57cec5SDimitry Andric     Counter ExitCount = getRegion().getCounter();
6950b57cec5SDimitry Andric     popRegions(Index);
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric     // The statement may be spanned by an expansion. Make sure we handle a file
6980b57cec5SDimitry Andric     // exit out of this expansion before moving to the next statement.
6990b57cec5SDimitry Andric     if (SM.isBeforeInTranslationUnit(StartLoc, S->getBeginLoc()))
7000b57cec5SDimitry Andric       MostRecentLocation = EndLoc;
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric     return ExitCount;
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric 
705af732203SDimitry Andric   /// Determine whether the given condition can be constant folded.
ConditionFoldsToBool__anone2f8b4240211::CounterCoverageMappingBuilder706af732203SDimitry Andric   bool ConditionFoldsToBool(const Expr *Cond) {
707af732203SDimitry Andric     Expr::EvalResult Result;
708af732203SDimitry Andric     return (Cond->EvaluateAsInt(Result, CVM.getCodeGenModule().getContext()));
709af732203SDimitry Andric   }
710af732203SDimitry Andric 
711af732203SDimitry Andric   /// Create a Branch Region around an instrumentable condition for coverage
712af732203SDimitry Andric   /// and add it to the function's SourceRegions.  A branch region tracks a
713af732203SDimitry Andric   /// "True" counter and a "False" counter for boolean expressions that
714af732203SDimitry Andric   /// result in the generation of a branch.
createBranchRegion__anone2f8b4240211::CounterCoverageMappingBuilder715af732203SDimitry Andric   void createBranchRegion(const Expr *C, Counter TrueCnt, Counter FalseCnt) {
716af732203SDimitry Andric     // Check for NULL conditions.
717af732203SDimitry Andric     if (!C)
718af732203SDimitry Andric       return;
719af732203SDimitry Andric 
720af732203SDimitry Andric     // Ensure we are an instrumentable condition (i.e. no "&&" or "||").  Push
721af732203SDimitry Andric     // region onto RegionStack but immediately pop it (which adds it to the
722af732203SDimitry Andric     // function's SourceRegions) because it doesn't apply to any other source
723af732203SDimitry Andric     // code other than the Condition.
724af732203SDimitry Andric     if (CodeGenFunction::isInstrumentedCondition(C)) {
725af732203SDimitry Andric       // If a condition can fold to true or false, the corresponding branch
726af732203SDimitry Andric       // will be removed.  Create a region with both counters hard-coded to
727af732203SDimitry Andric       // zero. This allows us to visualize them in a special way.
728af732203SDimitry Andric       // Alternatively, we can prevent any optimization done via
729af732203SDimitry Andric       // constant-folding by ensuring that ConstantFoldsToSimpleInteger() in
730af732203SDimitry Andric       // CodeGenFunction.c always returns false, but that is very heavy-handed.
731af732203SDimitry Andric       if (ConditionFoldsToBool(C))
732af732203SDimitry Andric         popRegions(pushRegion(Counter::getZero(), getStart(C), getEnd(C),
733af732203SDimitry Andric                               Counter::getZero()));
734af732203SDimitry Andric       else
735af732203SDimitry Andric         // Otherwise, create a region with the True counter and False counter.
736af732203SDimitry Andric         popRegions(pushRegion(TrueCnt, getStart(C), getEnd(C), FalseCnt));
737af732203SDimitry Andric     }
738af732203SDimitry Andric   }
739af732203SDimitry Andric 
740af732203SDimitry Andric   /// Create a Branch Region around a SwitchCase for code coverage
741af732203SDimitry Andric   /// and add it to the function's SourceRegions.
createSwitchCaseRegion__anone2f8b4240211::CounterCoverageMappingBuilder742af732203SDimitry Andric   void createSwitchCaseRegion(const SwitchCase *SC, Counter TrueCnt,
743af732203SDimitry Andric                               Counter FalseCnt) {
744af732203SDimitry Andric     // Push region onto RegionStack but immediately pop it (which adds it to
745af732203SDimitry Andric     // the function's SourceRegions) because it doesn't apply to any other
746af732203SDimitry Andric     // source other than the SwitchCase.
747af732203SDimitry Andric     popRegions(pushRegion(TrueCnt, getStart(SC), SC->getColonLoc(), FalseCnt));
748af732203SDimitry Andric   }
749af732203SDimitry Andric 
7500b57cec5SDimitry Andric   /// Check whether a region with bounds \c StartLoc and \c EndLoc
7510b57cec5SDimitry Andric   /// is already added to \c SourceRegions.
isRegionAlreadyAdded__anone2f8b4240211::CounterCoverageMappingBuilder752af732203SDimitry Andric   bool isRegionAlreadyAdded(SourceLocation StartLoc, SourceLocation EndLoc,
753af732203SDimitry Andric                             bool isBranch = false) {
7540b57cec5SDimitry Andric     return SourceRegions.rend() !=
7550b57cec5SDimitry Andric            std::find_if(SourceRegions.rbegin(), SourceRegions.rend(),
7560b57cec5SDimitry Andric                         [&](const SourceMappingRegion &Region) {
7570b57cec5SDimitry Andric                           return Region.getBeginLoc() == StartLoc &&
758af732203SDimitry Andric                                  Region.getEndLoc() == EndLoc &&
759af732203SDimitry Andric                                  Region.isBranch() == isBranch;
7600b57cec5SDimitry Andric                         });
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   /// Adjust the most recently visited location to \c EndLoc.
7640b57cec5SDimitry Andric   ///
7650b57cec5SDimitry Andric   /// This should be used after visiting any statements in non-source order.
adjustForOutOfOrderTraversal__anone2f8b4240211::CounterCoverageMappingBuilder7660b57cec5SDimitry Andric   void adjustForOutOfOrderTraversal(SourceLocation EndLoc) {
7670b57cec5SDimitry Andric     MostRecentLocation = EndLoc;
7680b57cec5SDimitry Andric     // The code region for a whole macro is created in handleFileExit() when
7690b57cec5SDimitry Andric     // it detects exiting of the virtual file of that macro. If we visited
7700b57cec5SDimitry Andric     // statements in non-source order, we might already have such a region
7710b57cec5SDimitry Andric     // added, for example, if a body of a loop is divided among multiple
7720b57cec5SDimitry Andric     // macros. Avoid adding duplicate regions in such case.
7730b57cec5SDimitry Andric     if (getRegion().hasEndLoc() &&
7740b57cec5SDimitry Andric         MostRecentLocation == getEndOfFileOrMacro(MostRecentLocation) &&
7750b57cec5SDimitry Andric         isRegionAlreadyAdded(getStartOfFileOrMacro(MostRecentLocation),
776af732203SDimitry Andric                              MostRecentLocation, getRegion().isBranch()))
7770b57cec5SDimitry Andric       MostRecentLocation = getIncludeOrExpansionLoc(MostRecentLocation);
7780b57cec5SDimitry Andric   }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   /// Adjust regions and state when \c NewLoc exits a file.
7810b57cec5SDimitry Andric   ///
7820b57cec5SDimitry Andric   /// If moving from our most recently tracked location to \c NewLoc exits any
7830b57cec5SDimitry Andric   /// files, this adjusts our current region stack and creates the file regions
7840b57cec5SDimitry Andric   /// for the exited file.
handleFileExit__anone2f8b4240211::CounterCoverageMappingBuilder7850b57cec5SDimitry Andric   void handleFileExit(SourceLocation NewLoc) {
7860b57cec5SDimitry Andric     if (NewLoc.isInvalid() ||
7870b57cec5SDimitry Andric         SM.isWrittenInSameFile(MostRecentLocation, NewLoc))
7880b57cec5SDimitry Andric       return;
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric     // If NewLoc is not in a file that contains MostRecentLocation, walk up to
7910b57cec5SDimitry Andric     // find the common ancestor.
7920b57cec5SDimitry Andric     SourceLocation LCA = NewLoc;
7930b57cec5SDimitry Andric     FileID ParentFile = SM.getFileID(LCA);
7940b57cec5SDimitry Andric     while (!isNestedIn(MostRecentLocation, ParentFile)) {
7950b57cec5SDimitry Andric       LCA = getIncludeOrExpansionLoc(LCA);
7960b57cec5SDimitry Andric       if (LCA.isInvalid() || SM.isWrittenInSameFile(LCA, MostRecentLocation)) {
7970b57cec5SDimitry Andric         // Since there isn't a common ancestor, no file was exited. We just need
7980b57cec5SDimitry Andric         // to adjust our location to the new file.
7990b57cec5SDimitry Andric         MostRecentLocation = NewLoc;
8000b57cec5SDimitry Andric         return;
8010b57cec5SDimitry Andric       }
8020b57cec5SDimitry Andric       ParentFile = SM.getFileID(LCA);
8030b57cec5SDimitry Andric     }
8040b57cec5SDimitry Andric 
8050b57cec5SDimitry Andric     llvm::SmallSet<SourceLocation, 8> StartLocs;
8060b57cec5SDimitry Andric     Optional<Counter> ParentCounter;
8070b57cec5SDimitry Andric     for (SourceMappingRegion &I : llvm::reverse(RegionStack)) {
8080b57cec5SDimitry Andric       if (!I.hasStartLoc())
8090b57cec5SDimitry Andric         continue;
8100b57cec5SDimitry Andric       SourceLocation Loc = I.getBeginLoc();
8110b57cec5SDimitry Andric       if (!isNestedIn(Loc, ParentFile)) {
8120b57cec5SDimitry Andric         ParentCounter = I.getCounter();
8130b57cec5SDimitry Andric         break;
8140b57cec5SDimitry Andric       }
8150b57cec5SDimitry Andric 
8160b57cec5SDimitry Andric       while (!SM.isInFileID(Loc, ParentFile)) {
8170b57cec5SDimitry Andric         // The most nested region for each start location is the one with the
8180b57cec5SDimitry Andric         // correct count. We avoid creating redundant regions by stopping once
8190b57cec5SDimitry Andric         // we've seen this region.
820af732203SDimitry Andric         if (StartLocs.insert(Loc).second) {
821af732203SDimitry Andric           if (I.isBranch())
822af732203SDimitry Andric             SourceRegions.emplace_back(I.getCounter(), I.getFalseCounter(), Loc,
823af732203SDimitry Andric                                        getEndOfFileOrMacro(Loc), I.isBranch());
824af732203SDimitry Andric           else
8250b57cec5SDimitry Andric             SourceRegions.emplace_back(I.getCounter(), Loc,
8260b57cec5SDimitry Andric                                        getEndOfFileOrMacro(Loc));
827af732203SDimitry Andric         }
8280b57cec5SDimitry Andric         Loc = getIncludeOrExpansionLoc(Loc);
8290b57cec5SDimitry Andric       }
8300b57cec5SDimitry Andric       I.setStartLoc(getPreciseTokenLocEnd(Loc));
8310b57cec5SDimitry Andric     }
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric     if (ParentCounter) {
8340b57cec5SDimitry Andric       // If the file is contained completely by another region and doesn't
8350b57cec5SDimitry Andric       // immediately start its own region, the whole file gets a region
8360b57cec5SDimitry Andric       // corresponding to the parent.
8370b57cec5SDimitry Andric       SourceLocation Loc = MostRecentLocation;
8380b57cec5SDimitry Andric       while (isNestedIn(Loc, ParentFile)) {
8390b57cec5SDimitry Andric         SourceLocation FileStart = getStartOfFileOrMacro(Loc);
8400b57cec5SDimitry Andric         if (StartLocs.insert(FileStart).second) {
8410b57cec5SDimitry Andric           SourceRegions.emplace_back(*ParentCounter, FileStart,
8420b57cec5SDimitry Andric                                      getEndOfFileOrMacro(Loc));
8430b57cec5SDimitry Andric           assert(SpellingRegion(SM, SourceRegions.back()).isInSourceOrder());
8440b57cec5SDimitry Andric         }
8450b57cec5SDimitry Andric         Loc = getIncludeOrExpansionLoc(Loc);
8460b57cec5SDimitry Andric       }
8470b57cec5SDimitry Andric     }
8480b57cec5SDimitry Andric 
8490b57cec5SDimitry Andric     MostRecentLocation = NewLoc;
8500b57cec5SDimitry Andric   }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric   /// Ensure that \c S is included in the current region.
extendRegion__anone2f8b4240211::CounterCoverageMappingBuilder8530b57cec5SDimitry Andric   void extendRegion(const Stmt *S) {
8540b57cec5SDimitry Andric     SourceMappingRegion &Region = getRegion();
8550b57cec5SDimitry Andric     SourceLocation StartLoc = getStart(S);
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric     handleFileExit(StartLoc);
8580b57cec5SDimitry Andric     if (!Region.hasStartLoc())
8590b57cec5SDimitry Andric       Region.setStartLoc(StartLoc);
8600b57cec5SDimitry Andric   }
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   /// Mark \c S as a terminator, starting a zero region.
terminateRegion__anone2f8b4240211::CounterCoverageMappingBuilder8630b57cec5SDimitry Andric   void terminateRegion(const Stmt *S) {
8640b57cec5SDimitry Andric     extendRegion(S);
8650b57cec5SDimitry Andric     SourceMappingRegion &Region = getRegion();
8660b57cec5SDimitry Andric     SourceLocation EndLoc = getEnd(S);
8670b57cec5SDimitry Andric     if (!Region.hasEndLoc())
8680b57cec5SDimitry Andric       Region.setEndLoc(EndLoc);
8690b57cec5SDimitry Andric     pushRegion(Counter::getZero());
870*5f7ddb14SDimitry Andric     HasTerminateStmt = true;
8710b57cec5SDimitry Andric   }
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   /// Find a valid gap range between \p AfterLoc and \p BeforeLoc.
findGapAreaBetween__anone2f8b4240211::CounterCoverageMappingBuilder8740b57cec5SDimitry Andric   Optional<SourceRange> findGapAreaBetween(SourceLocation AfterLoc,
8750b57cec5SDimitry Andric                                            SourceLocation BeforeLoc) {
876*5f7ddb14SDimitry Andric     // If AfterLoc is in function-like macro, use the right parenthesis
877*5f7ddb14SDimitry Andric     // location.
878*5f7ddb14SDimitry Andric     if (AfterLoc.isMacroID()) {
879*5f7ddb14SDimitry Andric       FileID FID = SM.getFileID(AfterLoc);
880*5f7ddb14SDimitry Andric       const SrcMgr::ExpansionInfo *EI = &SM.getSLocEntry(FID).getExpansion();
881*5f7ddb14SDimitry Andric       if (EI->isFunctionMacroExpansion())
882*5f7ddb14SDimitry Andric         AfterLoc = EI->getExpansionLocEnd();
883*5f7ddb14SDimitry Andric     }
884*5f7ddb14SDimitry Andric 
885*5f7ddb14SDimitry Andric     size_t StartDepth = locationDepth(AfterLoc);
886*5f7ddb14SDimitry Andric     size_t EndDepth = locationDepth(BeforeLoc);
887*5f7ddb14SDimitry Andric     while (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc)) {
888*5f7ddb14SDimitry Andric       bool UnnestStart = StartDepth >= EndDepth;
889*5f7ddb14SDimitry Andric       bool UnnestEnd = EndDepth >= StartDepth;
890*5f7ddb14SDimitry Andric       if (UnnestEnd) {
891*5f7ddb14SDimitry Andric         assert(SM.isWrittenInSameFile(getStartOfFileOrMacro(BeforeLoc),
892*5f7ddb14SDimitry Andric                                       BeforeLoc));
893*5f7ddb14SDimitry Andric 
894*5f7ddb14SDimitry Andric         BeforeLoc = getIncludeOrExpansionLoc(BeforeLoc);
895*5f7ddb14SDimitry Andric         assert(BeforeLoc.isValid());
896*5f7ddb14SDimitry Andric         EndDepth--;
897*5f7ddb14SDimitry Andric       }
898*5f7ddb14SDimitry Andric       if (UnnestStart) {
899*5f7ddb14SDimitry Andric         assert(SM.isWrittenInSameFile(AfterLoc,
900*5f7ddb14SDimitry Andric                                       getEndOfFileOrMacro(AfterLoc)));
901*5f7ddb14SDimitry Andric 
902*5f7ddb14SDimitry Andric         AfterLoc = getIncludeOrExpansionLoc(AfterLoc);
903*5f7ddb14SDimitry Andric         assert(AfterLoc.isValid());
904*5f7ddb14SDimitry Andric         AfterLoc = getPreciseTokenLocEnd(AfterLoc);
905*5f7ddb14SDimitry Andric         assert(AfterLoc.isValid());
906*5f7ddb14SDimitry Andric         StartDepth--;
907*5f7ddb14SDimitry Andric       }
908*5f7ddb14SDimitry Andric     }
909*5f7ddb14SDimitry Andric     AfterLoc = getPreciseTokenLocEnd(AfterLoc);
9100b57cec5SDimitry Andric     // If the start and end locations of the gap are both within the same macro
9110b57cec5SDimitry Andric     // file, the range may not be in source order.
9120b57cec5SDimitry Andric     if (AfterLoc.isMacroID() || BeforeLoc.isMacroID())
9130b57cec5SDimitry Andric       return None;
914*5f7ddb14SDimitry Andric     if (!SM.isWrittenInSameFile(AfterLoc, BeforeLoc) ||
915*5f7ddb14SDimitry Andric         !SpellingRegion(SM, AfterLoc, BeforeLoc).isInSourceOrder())
9160b57cec5SDimitry Andric       return None;
9170b57cec5SDimitry Andric     return {{AfterLoc, BeforeLoc}};
9180b57cec5SDimitry Andric   }
9190b57cec5SDimitry Andric 
9200b57cec5SDimitry Andric   /// Emit a gap region between \p StartLoc and \p EndLoc with the given count.
fillGapAreaWithCount__anone2f8b4240211::CounterCoverageMappingBuilder9210b57cec5SDimitry Andric   void fillGapAreaWithCount(SourceLocation StartLoc, SourceLocation EndLoc,
9220b57cec5SDimitry Andric                             Counter Count) {
9230b57cec5SDimitry Andric     if (StartLoc == EndLoc)
9240b57cec5SDimitry Andric       return;
9250b57cec5SDimitry Andric     assert(SpellingRegion(SM, StartLoc, EndLoc).isInSourceOrder());
9260b57cec5SDimitry Andric     handleFileExit(StartLoc);
9270b57cec5SDimitry Andric     size_t Index = pushRegion(Count, StartLoc, EndLoc);
9280b57cec5SDimitry Andric     getRegion().setGap(true);
9290b57cec5SDimitry Andric     handleFileExit(EndLoc);
9300b57cec5SDimitry Andric     popRegions(Index);
9310b57cec5SDimitry Andric   }
9320b57cec5SDimitry Andric 
9330b57cec5SDimitry Andric   /// Keep counts of breaks and continues inside loops.
9340b57cec5SDimitry Andric   struct BreakContinue {
9350b57cec5SDimitry Andric     Counter BreakCount;
9360b57cec5SDimitry Andric     Counter ContinueCount;
9370b57cec5SDimitry Andric   };
9380b57cec5SDimitry Andric   SmallVector<BreakContinue, 8> BreakContinueStack;
9390b57cec5SDimitry Andric 
CounterCoverageMappingBuilder__anone2f8b4240211::CounterCoverageMappingBuilder9400b57cec5SDimitry Andric   CounterCoverageMappingBuilder(
9410b57cec5SDimitry Andric       CoverageMappingModuleGen &CVM,
9420b57cec5SDimitry Andric       llvm::DenseMap<const Stmt *, unsigned> &CounterMap, SourceManager &SM,
9430b57cec5SDimitry Andric       const LangOptions &LangOpts)
944*5f7ddb14SDimitry Andric       : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap) {}
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   /// Write the mapping data to the output stream
write__anone2f8b4240211::CounterCoverageMappingBuilder9470b57cec5SDimitry Andric   void write(llvm::raw_ostream &OS) {
9480b57cec5SDimitry Andric     llvm::SmallVector<unsigned, 8> VirtualFileMapping;
9490b57cec5SDimitry Andric     gatherFileIDs(VirtualFileMapping);
9500b57cec5SDimitry Andric     SourceRegionFilter Filter = emitExpansionRegions();
9510b57cec5SDimitry Andric     emitSourceRegions(Filter);
9520b57cec5SDimitry Andric     gatherSkippedRegions();
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric     if (MappingRegions.empty())
9550b57cec5SDimitry Andric       return;
9560b57cec5SDimitry Andric 
9570b57cec5SDimitry Andric     CoverageMappingWriter Writer(VirtualFileMapping, Builder.getExpressions(),
9580b57cec5SDimitry Andric                                  MappingRegions);
9590b57cec5SDimitry Andric     Writer.write(OS);
9600b57cec5SDimitry Andric   }
9610b57cec5SDimitry Andric 
VisitStmt__anone2f8b4240211::CounterCoverageMappingBuilder9620b57cec5SDimitry Andric   void VisitStmt(const Stmt *S) {
9630b57cec5SDimitry Andric     if (S->getBeginLoc().isValid())
9640b57cec5SDimitry Andric       extendRegion(S);
965*5f7ddb14SDimitry Andric     const Stmt *LastStmt = nullptr;
966*5f7ddb14SDimitry Andric     bool SaveTerminateStmt = HasTerminateStmt;
967*5f7ddb14SDimitry Andric     HasTerminateStmt = false;
968*5f7ddb14SDimitry Andric     GapRegionCounter = Counter::getZero();
9690b57cec5SDimitry Andric     for (const Stmt *Child : S->children())
970*5f7ddb14SDimitry Andric       if (Child) {
971*5f7ddb14SDimitry Andric         // If last statement contains terminate statements, add a gap area
972*5f7ddb14SDimitry Andric         // between the two statements. Skipping attributed statements, because
973*5f7ddb14SDimitry Andric         // they don't have valid start location.
974*5f7ddb14SDimitry Andric         if (LastStmt && HasTerminateStmt && !dyn_cast<AttributedStmt>(Child)) {
975*5f7ddb14SDimitry Andric           auto Gap = findGapAreaBetween(getEnd(LastStmt), getStart(Child));
976*5f7ddb14SDimitry Andric           if (Gap)
977*5f7ddb14SDimitry Andric             fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(),
978*5f7ddb14SDimitry Andric                                  GapRegionCounter);
979*5f7ddb14SDimitry Andric           SaveTerminateStmt = true;
980*5f7ddb14SDimitry Andric           HasTerminateStmt = false;
981*5f7ddb14SDimitry Andric         }
9820b57cec5SDimitry Andric         this->Visit(Child);
983*5f7ddb14SDimitry Andric         LastStmt = Child;
984*5f7ddb14SDimitry Andric       }
985*5f7ddb14SDimitry Andric     if (SaveTerminateStmt)
986*5f7ddb14SDimitry Andric       HasTerminateStmt = true;
9870b57cec5SDimitry Andric     handleFileExit(getEnd(S));
9880b57cec5SDimitry Andric   }
9890b57cec5SDimitry Andric 
VisitDecl__anone2f8b4240211::CounterCoverageMappingBuilder9900b57cec5SDimitry Andric   void VisitDecl(const Decl *D) {
9910b57cec5SDimitry Andric     Stmt *Body = D->getBody();
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric     // Do not propagate region counts into system headers.
9940b57cec5SDimitry Andric     if (Body && SM.isInSystemHeader(SM.getSpellingLoc(getStart(Body))))
9950b57cec5SDimitry Andric       return;
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric     // Do not visit the artificial children nodes of defaulted methods. The
9980b57cec5SDimitry Andric     // lexer may not be able to report back precise token end locations for
9990b57cec5SDimitry Andric     // these children nodes (llvm.org/PR39822), and moreover users will not be
10000b57cec5SDimitry Andric     // able to see coverage for them.
10010b57cec5SDimitry Andric     bool Defaulted = false;
10020b57cec5SDimitry Andric     if (auto *Method = dyn_cast<CXXMethodDecl>(D))
10030b57cec5SDimitry Andric       Defaulted = Method->isDefaulted();
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric     propagateCounts(getRegionCounter(Body), Body,
10060b57cec5SDimitry Andric                     /*VisitChildren=*/!Defaulted);
10070b57cec5SDimitry Andric     assert(RegionStack.empty() && "Regions entered but never exited");
10080b57cec5SDimitry Andric   }
10090b57cec5SDimitry Andric 
VisitReturnStmt__anone2f8b4240211::CounterCoverageMappingBuilder10100b57cec5SDimitry Andric   void VisitReturnStmt(const ReturnStmt *S) {
10110b57cec5SDimitry Andric     extendRegion(S);
10120b57cec5SDimitry Andric     if (S->getRetValue())
10130b57cec5SDimitry Andric       Visit(S->getRetValue());
10140b57cec5SDimitry Andric     terminateRegion(S);
10150b57cec5SDimitry Andric   }
10160b57cec5SDimitry Andric 
VisitCoroutineBodyStmt__anone2f8b4240211::CounterCoverageMappingBuilder10175ffd83dbSDimitry Andric   void VisitCoroutineBodyStmt(const CoroutineBodyStmt *S) {
10185ffd83dbSDimitry Andric     extendRegion(S);
10195ffd83dbSDimitry Andric     Visit(S->getBody());
10205ffd83dbSDimitry Andric   }
10215ffd83dbSDimitry Andric 
VisitCoreturnStmt__anone2f8b4240211::CounterCoverageMappingBuilder10225ffd83dbSDimitry Andric   void VisitCoreturnStmt(const CoreturnStmt *S) {
10235ffd83dbSDimitry Andric     extendRegion(S);
10245ffd83dbSDimitry Andric     if (S->getOperand())
10255ffd83dbSDimitry Andric       Visit(S->getOperand());
10265ffd83dbSDimitry Andric     terminateRegion(S);
10275ffd83dbSDimitry Andric   }
10285ffd83dbSDimitry Andric 
VisitCXXThrowExpr__anone2f8b4240211::CounterCoverageMappingBuilder10290b57cec5SDimitry Andric   void VisitCXXThrowExpr(const CXXThrowExpr *E) {
10300b57cec5SDimitry Andric     extendRegion(E);
10310b57cec5SDimitry Andric     if (E->getSubExpr())
10320b57cec5SDimitry Andric       Visit(E->getSubExpr());
10330b57cec5SDimitry Andric     terminateRegion(E);
10340b57cec5SDimitry Andric   }
10350b57cec5SDimitry Andric 
VisitGotoStmt__anone2f8b4240211::CounterCoverageMappingBuilder10360b57cec5SDimitry Andric   void VisitGotoStmt(const GotoStmt *S) { terminateRegion(S); }
10370b57cec5SDimitry Andric 
VisitLabelStmt__anone2f8b4240211::CounterCoverageMappingBuilder10380b57cec5SDimitry Andric   void VisitLabelStmt(const LabelStmt *S) {
10390b57cec5SDimitry Andric     Counter LabelCount = getRegionCounter(S);
10400b57cec5SDimitry Andric     SourceLocation Start = getStart(S);
10410b57cec5SDimitry Andric     // We can't extendRegion here or we risk overlapping with our new region.
10420b57cec5SDimitry Andric     handleFileExit(Start);
10430b57cec5SDimitry Andric     pushRegion(LabelCount, Start);
10440b57cec5SDimitry Andric     Visit(S->getSubStmt());
10450b57cec5SDimitry Andric   }
10460b57cec5SDimitry Andric 
VisitBreakStmt__anone2f8b4240211::CounterCoverageMappingBuilder10470b57cec5SDimitry Andric   void VisitBreakStmt(const BreakStmt *S) {
10480b57cec5SDimitry Andric     assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
10490b57cec5SDimitry Andric     BreakContinueStack.back().BreakCount = addCounters(
10500b57cec5SDimitry Andric         BreakContinueStack.back().BreakCount, getRegion().getCounter());
10510b57cec5SDimitry Andric     // FIXME: a break in a switch should terminate regions for all preceding
10520b57cec5SDimitry Andric     // case statements, not just the most recent one.
10530b57cec5SDimitry Andric     terminateRegion(S);
10540b57cec5SDimitry Andric   }
10550b57cec5SDimitry Andric 
VisitContinueStmt__anone2f8b4240211::CounterCoverageMappingBuilder10560b57cec5SDimitry Andric   void VisitContinueStmt(const ContinueStmt *S) {
10570b57cec5SDimitry Andric     assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
10580b57cec5SDimitry Andric     BreakContinueStack.back().ContinueCount = addCounters(
10590b57cec5SDimitry Andric         BreakContinueStack.back().ContinueCount, getRegion().getCounter());
10600b57cec5SDimitry Andric     terminateRegion(S);
10610b57cec5SDimitry Andric   }
10620b57cec5SDimitry Andric 
VisitCallExpr__anone2f8b4240211::CounterCoverageMappingBuilder10630b57cec5SDimitry Andric   void VisitCallExpr(const CallExpr *E) {
10640b57cec5SDimitry Andric     VisitStmt(E);
10650b57cec5SDimitry Andric 
10660b57cec5SDimitry Andric     // Terminate the region when we hit a noreturn function.
10670b57cec5SDimitry Andric     // (This is helpful dealing with switch statements.)
10680b57cec5SDimitry Andric     QualType CalleeType = E->getCallee()->getType();
10690b57cec5SDimitry Andric     if (getFunctionExtInfo(*CalleeType).getNoReturn())
10700b57cec5SDimitry Andric       terminateRegion(E);
10710b57cec5SDimitry Andric   }
10720b57cec5SDimitry Andric 
VisitWhileStmt__anone2f8b4240211::CounterCoverageMappingBuilder10730b57cec5SDimitry Andric   void VisitWhileStmt(const WhileStmt *S) {
10740b57cec5SDimitry Andric     extendRegion(S);
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
10770b57cec5SDimitry Andric     Counter BodyCount = getRegionCounter(S);
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric     // Handle the body first so that we can get the backedge count.
10800b57cec5SDimitry Andric     BreakContinueStack.push_back(BreakContinue());
10810b57cec5SDimitry Andric     extendRegion(S->getBody());
10820b57cec5SDimitry Andric     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
10830b57cec5SDimitry Andric     BreakContinue BC = BreakContinueStack.pop_back_val();
10840b57cec5SDimitry Andric 
1085*5f7ddb14SDimitry Andric     bool BodyHasTerminateStmt = HasTerminateStmt;
1086*5f7ddb14SDimitry Andric     HasTerminateStmt = false;
1087*5f7ddb14SDimitry Andric 
10880b57cec5SDimitry Andric     // Go back to handle the condition.
10890b57cec5SDimitry Andric     Counter CondCount =
10900b57cec5SDimitry Andric         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
10910b57cec5SDimitry Andric     propagateCounts(CondCount, S->getCond());
10920b57cec5SDimitry Andric     adjustForOutOfOrderTraversal(getEnd(S));
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric     // The body count applies to the area immediately after the increment.
1095*5f7ddb14SDimitry Andric     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
10960b57cec5SDimitry Andric     if (Gap)
10970b57cec5SDimitry Andric       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric     Counter OutCount =
11000b57cec5SDimitry Andric         addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1101*5f7ddb14SDimitry Andric     if (OutCount != ParentCount) {
11020b57cec5SDimitry Andric       pushRegion(OutCount);
1103*5f7ddb14SDimitry Andric       GapRegionCounter = OutCount;
1104*5f7ddb14SDimitry Andric       if (BodyHasTerminateStmt)
1105*5f7ddb14SDimitry Andric         HasTerminateStmt = true;
1106*5f7ddb14SDimitry Andric     }
1107af732203SDimitry Andric 
1108af732203SDimitry Andric     // Create Branch Region around condition.
1109af732203SDimitry Andric     createBranchRegion(S->getCond(), BodyCount,
1110af732203SDimitry Andric                        subtractCounters(CondCount, BodyCount));
11110b57cec5SDimitry Andric   }
11120b57cec5SDimitry Andric 
VisitDoStmt__anone2f8b4240211::CounterCoverageMappingBuilder11130b57cec5SDimitry Andric   void VisitDoStmt(const DoStmt *S) {
11140b57cec5SDimitry Andric     extendRegion(S);
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
11170b57cec5SDimitry Andric     Counter BodyCount = getRegionCounter(S);
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric     BreakContinueStack.push_back(BreakContinue());
11200b57cec5SDimitry Andric     extendRegion(S->getBody());
11210b57cec5SDimitry Andric     Counter BackedgeCount =
11220b57cec5SDimitry Andric         propagateCounts(addCounters(ParentCount, BodyCount), S->getBody());
11230b57cec5SDimitry Andric     BreakContinue BC = BreakContinueStack.pop_back_val();
11240b57cec5SDimitry Andric 
1125*5f7ddb14SDimitry Andric     bool BodyHasTerminateStmt = HasTerminateStmt;
1126*5f7ddb14SDimitry Andric     HasTerminateStmt = false;
1127*5f7ddb14SDimitry Andric 
11280b57cec5SDimitry Andric     Counter CondCount = addCounters(BackedgeCount, BC.ContinueCount);
11290b57cec5SDimitry Andric     propagateCounts(CondCount, S->getCond());
11300b57cec5SDimitry Andric 
11310b57cec5SDimitry Andric     Counter OutCount =
11320b57cec5SDimitry Andric         addCounters(BC.BreakCount, subtractCounters(CondCount, BodyCount));
1133*5f7ddb14SDimitry Andric     if (OutCount != ParentCount) {
11340b57cec5SDimitry Andric       pushRegion(OutCount);
1135*5f7ddb14SDimitry Andric       GapRegionCounter = OutCount;
1136*5f7ddb14SDimitry Andric     }
1137af732203SDimitry Andric 
1138af732203SDimitry Andric     // Create Branch Region around condition.
1139af732203SDimitry Andric     createBranchRegion(S->getCond(), BodyCount,
1140af732203SDimitry Andric                        subtractCounters(CondCount, BodyCount));
1141*5f7ddb14SDimitry Andric 
1142*5f7ddb14SDimitry Andric     if (BodyHasTerminateStmt)
1143*5f7ddb14SDimitry Andric       HasTerminateStmt = true;
11440b57cec5SDimitry Andric   }
11450b57cec5SDimitry Andric 
VisitForStmt__anone2f8b4240211::CounterCoverageMappingBuilder11460b57cec5SDimitry Andric   void VisitForStmt(const ForStmt *S) {
11470b57cec5SDimitry Andric     extendRegion(S);
11480b57cec5SDimitry Andric     if (S->getInit())
11490b57cec5SDimitry Andric       Visit(S->getInit());
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
11520b57cec5SDimitry Andric     Counter BodyCount = getRegionCounter(S);
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric     // The loop increment may contain a break or continue.
11550b57cec5SDimitry Andric     if (S->getInc())
11560b57cec5SDimitry Andric       BreakContinueStack.emplace_back();
11570b57cec5SDimitry Andric 
11580b57cec5SDimitry Andric     // Handle the body first so that we can get the backedge count.
11590b57cec5SDimitry Andric     BreakContinueStack.emplace_back();
11600b57cec5SDimitry Andric     extendRegion(S->getBody());
11610b57cec5SDimitry Andric     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
11620b57cec5SDimitry Andric     BreakContinue BodyBC = BreakContinueStack.pop_back_val();
11630b57cec5SDimitry Andric 
1164*5f7ddb14SDimitry Andric     bool BodyHasTerminateStmt = HasTerminateStmt;
1165*5f7ddb14SDimitry Andric     HasTerminateStmt = false;
1166*5f7ddb14SDimitry Andric 
11670b57cec5SDimitry Andric     // The increment is essentially part of the body but it needs to include
11680b57cec5SDimitry Andric     // the count for all the continue statements.
11690b57cec5SDimitry Andric     BreakContinue IncrementBC;
11700b57cec5SDimitry Andric     if (const Stmt *Inc = S->getInc()) {
11710b57cec5SDimitry Andric       propagateCounts(addCounters(BackedgeCount, BodyBC.ContinueCount), Inc);
11720b57cec5SDimitry Andric       IncrementBC = BreakContinueStack.pop_back_val();
11730b57cec5SDimitry Andric     }
11740b57cec5SDimitry Andric 
11750b57cec5SDimitry Andric     // Go back to handle the condition.
11760b57cec5SDimitry Andric     Counter CondCount = addCounters(
11770b57cec5SDimitry Andric         addCounters(ParentCount, BackedgeCount, BodyBC.ContinueCount),
11780b57cec5SDimitry Andric         IncrementBC.ContinueCount);
11790b57cec5SDimitry Andric     if (const Expr *Cond = S->getCond()) {
11800b57cec5SDimitry Andric       propagateCounts(CondCount, Cond);
11810b57cec5SDimitry Andric       adjustForOutOfOrderTraversal(getEnd(S));
11820b57cec5SDimitry Andric     }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric     // The body count applies to the area immediately after the increment.
1185*5f7ddb14SDimitry Andric     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
11860b57cec5SDimitry Andric     if (Gap)
11870b57cec5SDimitry Andric       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
11880b57cec5SDimitry Andric 
11890b57cec5SDimitry Andric     Counter OutCount = addCounters(BodyBC.BreakCount, IncrementBC.BreakCount,
11900b57cec5SDimitry Andric                                    subtractCounters(CondCount, BodyCount));
1191*5f7ddb14SDimitry Andric     if (OutCount != ParentCount) {
11920b57cec5SDimitry Andric       pushRegion(OutCount);
1193*5f7ddb14SDimitry Andric       GapRegionCounter = OutCount;
1194*5f7ddb14SDimitry Andric       if (BodyHasTerminateStmt)
1195*5f7ddb14SDimitry Andric         HasTerminateStmt = true;
1196*5f7ddb14SDimitry Andric     }
1197af732203SDimitry Andric 
1198af732203SDimitry Andric     // Create Branch Region around condition.
1199af732203SDimitry Andric     createBranchRegion(S->getCond(), BodyCount,
1200af732203SDimitry Andric                        subtractCounters(CondCount, BodyCount));
12010b57cec5SDimitry Andric   }
12020b57cec5SDimitry Andric 
VisitCXXForRangeStmt__anone2f8b4240211::CounterCoverageMappingBuilder12030b57cec5SDimitry Andric   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
12040b57cec5SDimitry Andric     extendRegion(S);
12050b57cec5SDimitry Andric     if (S->getInit())
12060b57cec5SDimitry Andric       Visit(S->getInit());
12070b57cec5SDimitry Andric     Visit(S->getLoopVarStmt());
12080b57cec5SDimitry Andric     Visit(S->getRangeStmt());
12090b57cec5SDimitry Andric 
12100b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
12110b57cec5SDimitry Andric     Counter BodyCount = getRegionCounter(S);
12120b57cec5SDimitry Andric 
12130b57cec5SDimitry Andric     BreakContinueStack.push_back(BreakContinue());
12140b57cec5SDimitry Andric     extendRegion(S->getBody());
12150b57cec5SDimitry Andric     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
12160b57cec5SDimitry Andric     BreakContinue BC = BreakContinueStack.pop_back_val();
12170b57cec5SDimitry Andric 
1218*5f7ddb14SDimitry Andric     bool BodyHasTerminateStmt = HasTerminateStmt;
1219*5f7ddb14SDimitry Andric     HasTerminateStmt = false;
1220*5f7ddb14SDimitry Andric 
12210b57cec5SDimitry Andric     // The body count applies to the area immediately after the range.
1222*5f7ddb14SDimitry Andric     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
12230b57cec5SDimitry Andric     if (Gap)
12240b57cec5SDimitry Andric       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric     Counter LoopCount =
12270b57cec5SDimitry Andric         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
12280b57cec5SDimitry Andric     Counter OutCount =
12290b57cec5SDimitry Andric         addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1230*5f7ddb14SDimitry Andric     if (OutCount != ParentCount) {
12310b57cec5SDimitry Andric       pushRegion(OutCount);
1232*5f7ddb14SDimitry Andric       GapRegionCounter = OutCount;
1233*5f7ddb14SDimitry Andric       if (BodyHasTerminateStmt)
1234*5f7ddb14SDimitry Andric         HasTerminateStmt = true;
1235*5f7ddb14SDimitry Andric     }
1236af732203SDimitry Andric 
1237af732203SDimitry Andric     // Create Branch Region around condition.
1238af732203SDimitry Andric     createBranchRegion(S->getCond(), BodyCount,
1239af732203SDimitry Andric                        subtractCounters(LoopCount, BodyCount));
12400b57cec5SDimitry Andric   }
12410b57cec5SDimitry Andric 
VisitObjCForCollectionStmt__anone2f8b4240211::CounterCoverageMappingBuilder12420b57cec5SDimitry Andric   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
12430b57cec5SDimitry Andric     extendRegion(S);
12440b57cec5SDimitry Andric     Visit(S->getElement());
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
12470b57cec5SDimitry Andric     Counter BodyCount = getRegionCounter(S);
12480b57cec5SDimitry Andric 
12490b57cec5SDimitry Andric     BreakContinueStack.push_back(BreakContinue());
12500b57cec5SDimitry Andric     extendRegion(S->getBody());
12510b57cec5SDimitry Andric     Counter BackedgeCount = propagateCounts(BodyCount, S->getBody());
12520b57cec5SDimitry Andric     BreakContinue BC = BreakContinueStack.pop_back_val();
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric     // The body count applies to the area immediately after the collection.
1255*5f7ddb14SDimitry Andric     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getBody()));
12560b57cec5SDimitry Andric     if (Gap)
12570b57cec5SDimitry Andric       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), BodyCount);
12580b57cec5SDimitry Andric 
12590b57cec5SDimitry Andric     Counter LoopCount =
12600b57cec5SDimitry Andric         addCounters(ParentCount, BackedgeCount, BC.ContinueCount);
12610b57cec5SDimitry Andric     Counter OutCount =
12620b57cec5SDimitry Andric         addCounters(BC.BreakCount, subtractCounters(LoopCount, BodyCount));
1263*5f7ddb14SDimitry Andric     if (OutCount != ParentCount) {
12640b57cec5SDimitry Andric       pushRegion(OutCount);
1265*5f7ddb14SDimitry Andric       GapRegionCounter = OutCount;
1266*5f7ddb14SDimitry Andric     }
12670b57cec5SDimitry Andric   }
12680b57cec5SDimitry Andric 
VisitSwitchStmt__anone2f8b4240211::CounterCoverageMappingBuilder12690b57cec5SDimitry Andric   void VisitSwitchStmt(const SwitchStmt *S) {
12700b57cec5SDimitry Andric     extendRegion(S);
12710b57cec5SDimitry Andric     if (S->getInit())
12720b57cec5SDimitry Andric       Visit(S->getInit());
12730b57cec5SDimitry Andric     Visit(S->getCond());
12740b57cec5SDimitry Andric 
12750b57cec5SDimitry Andric     BreakContinueStack.push_back(BreakContinue());
12760b57cec5SDimitry Andric 
12770b57cec5SDimitry Andric     const Stmt *Body = S->getBody();
12780b57cec5SDimitry Andric     extendRegion(Body);
12790b57cec5SDimitry Andric     if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
12800b57cec5SDimitry Andric       if (!CS->body_empty()) {
12810b57cec5SDimitry Andric         // Make a region for the body of the switch.  If the body starts with
12820b57cec5SDimitry Andric         // a case, that case will reuse this region; otherwise, this covers
12830b57cec5SDimitry Andric         // the unreachable code at the beginning of the switch body.
1284480093f4SDimitry Andric         size_t Index = pushRegion(Counter::getZero(), getStart(CS));
1285480093f4SDimitry Andric         getRegion().setGap(true);
1286*5f7ddb14SDimitry Andric         Visit(Body);
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric         // Set the end for the body of the switch, if it isn't already set.
12890b57cec5SDimitry Andric         for (size_t i = RegionStack.size(); i != Index; --i) {
12900b57cec5SDimitry Andric           if (!RegionStack[i - 1].hasEndLoc())
12910b57cec5SDimitry Andric             RegionStack[i - 1].setEndLoc(getEnd(CS->body_back()));
12920b57cec5SDimitry Andric         }
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric         popRegions(Index);
12950b57cec5SDimitry Andric       }
12960b57cec5SDimitry Andric     } else
12970b57cec5SDimitry Andric       propagateCounts(Counter::getZero(), Body);
12980b57cec5SDimitry Andric     BreakContinue BC = BreakContinueStack.pop_back_val();
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric     if (!BreakContinueStack.empty())
13010b57cec5SDimitry Andric       BreakContinueStack.back().ContinueCount = addCounters(
13020b57cec5SDimitry Andric           BreakContinueStack.back().ContinueCount, BC.ContinueCount);
13030b57cec5SDimitry Andric 
1304af732203SDimitry Andric     Counter ParentCount = getRegion().getCounter();
13050b57cec5SDimitry Andric     Counter ExitCount = getRegionCounter(S);
13060b57cec5SDimitry Andric     SourceLocation ExitLoc = getEnd(S);
13070b57cec5SDimitry Andric     pushRegion(ExitCount);
1308*5f7ddb14SDimitry Andric     GapRegionCounter = ExitCount;
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric     // Ensure that handleFileExit recognizes when the end location is located
13110b57cec5SDimitry Andric     // in a different file.
13120b57cec5SDimitry Andric     MostRecentLocation = getStart(S);
13130b57cec5SDimitry Andric     handleFileExit(ExitLoc);
1314af732203SDimitry Andric 
1315af732203SDimitry Andric     // Create a Branch Region around each Case. Subtract the case's
1316af732203SDimitry Andric     // counter from the Parent counter to track the "False" branch count.
1317af732203SDimitry Andric     Counter CaseCountSum;
1318af732203SDimitry Andric     bool HasDefaultCase = false;
1319af732203SDimitry Andric     const SwitchCase *Case = S->getSwitchCaseList();
1320af732203SDimitry Andric     for (; Case; Case = Case->getNextSwitchCase()) {
1321af732203SDimitry Andric       HasDefaultCase = HasDefaultCase || isa<DefaultStmt>(Case);
1322af732203SDimitry Andric       CaseCountSum = addCounters(CaseCountSum, getRegionCounter(Case));
1323af732203SDimitry Andric       createSwitchCaseRegion(
1324af732203SDimitry Andric           Case, getRegionCounter(Case),
1325af732203SDimitry Andric           subtractCounters(ParentCount, getRegionCounter(Case)));
1326af732203SDimitry Andric     }
1327af732203SDimitry Andric 
1328af732203SDimitry Andric     // If no explicit default case exists, create a branch region to represent
1329af732203SDimitry Andric     // the hidden branch, which will be added later by the CodeGen. This region
1330af732203SDimitry Andric     // will be associated with the switch statement's condition.
1331af732203SDimitry Andric     if (!HasDefaultCase) {
1332af732203SDimitry Andric       Counter DefaultTrue = subtractCounters(ParentCount, CaseCountSum);
1333af732203SDimitry Andric       Counter DefaultFalse = subtractCounters(ParentCount, DefaultTrue);
1334af732203SDimitry Andric       createBranchRegion(S->getCond(), DefaultTrue, DefaultFalse);
1335af732203SDimitry Andric     }
13360b57cec5SDimitry Andric   }
13370b57cec5SDimitry Andric 
VisitSwitchCase__anone2f8b4240211::CounterCoverageMappingBuilder13380b57cec5SDimitry Andric   void VisitSwitchCase(const SwitchCase *S) {
13390b57cec5SDimitry Andric     extendRegion(S);
13400b57cec5SDimitry Andric 
13410b57cec5SDimitry Andric     SourceMappingRegion &Parent = getRegion();
13420b57cec5SDimitry Andric 
13430b57cec5SDimitry Andric     Counter Count = addCounters(Parent.getCounter(), getRegionCounter(S));
13440b57cec5SDimitry Andric     // Reuse the existing region if it starts at our label. This is typical of
13450b57cec5SDimitry Andric     // the first case in a switch.
13460b57cec5SDimitry Andric     if (Parent.hasStartLoc() && Parent.getBeginLoc() == getStart(S))
13470b57cec5SDimitry Andric       Parent.setCounter(Count);
13480b57cec5SDimitry Andric     else
13490b57cec5SDimitry Andric       pushRegion(Count, getStart(S));
13500b57cec5SDimitry Andric 
1351*5f7ddb14SDimitry Andric     GapRegionCounter = Count;
1352*5f7ddb14SDimitry Andric 
13530b57cec5SDimitry Andric     if (const auto *CS = dyn_cast<CaseStmt>(S)) {
13540b57cec5SDimitry Andric       Visit(CS->getLHS());
13550b57cec5SDimitry Andric       if (const Expr *RHS = CS->getRHS())
13560b57cec5SDimitry Andric         Visit(RHS);
13570b57cec5SDimitry Andric     }
13580b57cec5SDimitry Andric     Visit(S->getSubStmt());
13590b57cec5SDimitry Andric   }
13600b57cec5SDimitry Andric 
VisitIfStmt__anone2f8b4240211::CounterCoverageMappingBuilder13610b57cec5SDimitry Andric   void VisitIfStmt(const IfStmt *S) {
13620b57cec5SDimitry Andric     extendRegion(S);
13630b57cec5SDimitry Andric     if (S->getInit())
13640b57cec5SDimitry Andric       Visit(S->getInit());
13650b57cec5SDimitry Andric 
13660b57cec5SDimitry Andric     // Extend into the condition before we propagate through it below - this is
13670b57cec5SDimitry Andric     // needed to handle macros that generate the "if" but not the condition.
13680b57cec5SDimitry Andric     extendRegion(S->getCond());
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
13710b57cec5SDimitry Andric     Counter ThenCount = getRegionCounter(S);
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric     // Emitting a counter for the condition makes it easier to interpret the
13740b57cec5SDimitry Andric     // counter for the body when looking at the coverage.
13750b57cec5SDimitry Andric     propagateCounts(ParentCount, S->getCond());
13760b57cec5SDimitry Andric 
13770b57cec5SDimitry Andric     // The 'then' count applies to the area immediately after the condition.
1378*5f7ddb14SDimitry Andric     auto Gap = findGapAreaBetween(S->getRParenLoc(), getStart(S->getThen()));
13790b57cec5SDimitry Andric     if (Gap)
13800b57cec5SDimitry Andric       fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ThenCount);
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric     extendRegion(S->getThen());
13830b57cec5SDimitry Andric     Counter OutCount = propagateCounts(ThenCount, S->getThen());
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric     Counter ElseCount = subtractCounters(ParentCount, ThenCount);
13860b57cec5SDimitry Andric     if (const Stmt *Else = S->getElse()) {
1387*5f7ddb14SDimitry Andric       bool ThenHasTerminateStmt = HasTerminateStmt;
1388*5f7ddb14SDimitry Andric       HasTerminateStmt = false;
1389*5f7ddb14SDimitry Andric 
13900b57cec5SDimitry Andric       // The 'else' count applies to the area immediately after the 'then'.
1391*5f7ddb14SDimitry Andric       Gap = findGapAreaBetween(getEnd(S->getThen()), getStart(Else));
13920b57cec5SDimitry Andric       if (Gap)
13930b57cec5SDimitry Andric         fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), ElseCount);
13940b57cec5SDimitry Andric       extendRegion(Else);
13950b57cec5SDimitry Andric       OutCount = addCounters(OutCount, propagateCounts(ElseCount, Else));
1396*5f7ddb14SDimitry Andric 
1397*5f7ddb14SDimitry Andric       if (ThenHasTerminateStmt)
1398*5f7ddb14SDimitry Andric         HasTerminateStmt = true;
13990b57cec5SDimitry Andric     } else
14000b57cec5SDimitry Andric       OutCount = addCounters(OutCount, ElseCount);
14010b57cec5SDimitry Andric 
1402*5f7ddb14SDimitry Andric     if (OutCount != ParentCount) {
14030b57cec5SDimitry Andric       pushRegion(OutCount);
1404*5f7ddb14SDimitry Andric       GapRegionCounter = OutCount;
1405*5f7ddb14SDimitry Andric     }
1406af732203SDimitry Andric 
1407af732203SDimitry Andric     // Create Branch Region around condition.
1408af732203SDimitry Andric     createBranchRegion(S->getCond(), ThenCount,
1409af732203SDimitry Andric                        subtractCounters(ParentCount, ThenCount));
14100b57cec5SDimitry Andric   }
14110b57cec5SDimitry Andric 
VisitCXXTryStmt__anone2f8b4240211::CounterCoverageMappingBuilder14120b57cec5SDimitry Andric   void VisitCXXTryStmt(const CXXTryStmt *S) {
14130b57cec5SDimitry Andric     extendRegion(S);
14140b57cec5SDimitry Andric     // Handle macros that generate the "try" but not the rest.
14150b57cec5SDimitry Andric     extendRegion(S->getTryBlock());
14160b57cec5SDimitry Andric 
14170b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
14180b57cec5SDimitry Andric     propagateCounts(ParentCount, S->getTryBlock());
14190b57cec5SDimitry Andric 
14200b57cec5SDimitry Andric     for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
14210b57cec5SDimitry Andric       Visit(S->getHandler(I));
14220b57cec5SDimitry Andric 
14230b57cec5SDimitry Andric     Counter ExitCount = getRegionCounter(S);
14240b57cec5SDimitry Andric     pushRegion(ExitCount);
14250b57cec5SDimitry Andric   }
14260b57cec5SDimitry Andric 
VisitCXXCatchStmt__anone2f8b4240211::CounterCoverageMappingBuilder14270b57cec5SDimitry Andric   void VisitCXXCatchStmt(const CXXCatchStmt *S) {
14280b57cec5SDimitry Andric     propagateCounts(getRegionCounter(S), S->getHandlerBlock());
14290b57cec5SDimitry Andric   }
14300b57cec5SDimitry Andric 
VisitAbstractConditionalOperator__anone2f8b4240211::CounterCoverageMappingBuilder14310b57cec5SDimitry Andric   void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
14320b57cec5SDimitry Andric     extendRegion(E);
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric     Counter ParentCount = getRegion().getCounter();
14350b57cec5SDimitry Andric     Counter TrueCount = getRegionCounter(E);
14360b57cec5SDimitry Andric 
1437*5f7ddb14SDimitry Andric     propagateCounts(ParentCount, E->getCond());
14380b57cec5SDimitry Andric 
14390b57cec5SDimitry Andric     if (!isa<BinaryConditionalOperator>(E)) {
14400b57cec5SDimitry Andric       // The 'then' count applies to the area immediately after the condition.
14410b57cec5SDimitry Andric       auto Gap =
14420b57cec5SDimitry Andric           findGapAreaBetween(E->getQuestionLoc(), getStart(E->getTrueExpr()));
14430b57cec5SDimitry Andric       if (Gap)
14440b57cec5SDimitry Andric         fillGapAreaWithCount(Gap->getBegin(), Gap->getEnd(), TrueCount);
14450b57cec5SDimitry Andric 
14460b57cec5SDimitry Andric       extendRegion(E->getTrueExpr());
14470b57cec5SDimitry Andric       propagateCounts(TrueCount, E->getTrueExpr());
14480b57cec5SDimitry Andric     }
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric     extendRegion(E->getFalseExpr());
14510b57cec5SDimitry Andric     propagateCounts(subtractCounters(ParentCount, TrueCount),
14520b57cec5SDimitry Andric                     E->getFalseExpr());
1453af732203SDimitry Andric 
1454af732203SDimitry Andric     // Create Branch Region around condition.
1455af732203SDimitry Andric     createBranchRegion(E->getCond(), TrueCount,
1456af732203SDimitry Andric                        subtractCounters(ParentCount, TrueCount));
14570b57cec5SDimitry Andric   }
14580b57cec5SDimitry Andric 
VisitBinLAnd__anone2f8b4240211::CounterCoverageMappingBuilder14590b57cec5SDimitry Andric   void VisitBinLAnd(const BinaryOperator *E) {
14600b57cec5SDimitry Andric     extendRegion(E->getLHS());
14610b57cec5SDimitry Andric     propagateCounts(getRegion().getCounter(), E->getLHS());
14620b57cec5SDimitry Andric     handleFileExit(getEnd(E->getLHS()));
14630b57cec5SDimitry Andric 
1464af732203SDimitry Andric     // Counter tracks the right hand side of a logical and operator.
14650b57cec5SDimitry Andric     extendRegion(E->getRHS());
14660b57cec5SDimitry Andric     propagateCounts(getRegionCounter(E), E->getRHS());
1467af732203SDimitry Andric 
1468af732203SDimitry Andric     // Extract the RHS's Execution Counter.
1469af732203SDimitry Andric     Counter RHSExecCnt = getRegionCounter(E);
1470af732203SDimitry Andric 
1471af732203SDimitry Andric     // Extract the RHS's "True" Instance Counter.
1472af732203SDimitry Andric     Counter RHSTrueCnt = getRegionCounter(E->getRHS());
1473af732203SDimitry Andric 
1474af732203SDimitry Andric     // Extract the Parent Region Counter.
1475af732203SDimitry Andric     Counter ParentCnt = getRegion().getCounter();
1476af732203SDimitry Andric 
1477af732203SDimitry Andric     // Create Branch Region around LHS condition.
1478af732203SDimitry Andric     createBranchRegion(E->getLHS(), RHSExecCnt,
1479af732203SDimitry Andric                        subtractCounters(ParentCnt, RHSExecCnt));
1480af732203SDimitry Andric 
1481af732203SDimitry Andric     // Create Branch Region around RHS condition.
1482af732203SDimitry Andric     createBranchRegion(E->getRHS(), RHSTrueCnt,
1483af732203SDimitry Andric                        subtractCounters(RHSExecCnt, RHSTrueCnt));
14840b57cec5SDimitry Andric   }
14850b57cec5SDimitry Andric 
VisitBinLOr__anone2f8b4240211::CounterCoverageMappingBuilder14860b57cec5SDimitry Andric   void VisitBinLOr(const BinaryOperator *E) {
14870b57cec5SDimitry Andric     extendRegion(E->getLHS());
14880b57cec5SDimitry Andric     propagateCounts(getRegion().getCounter(), E->getLHS());
14890b57cec5SDimitry Andric     handleFileExit(getEnd(E->getLHS()));
14900b57cec5SDimitry Andric 
1491af732203SDimitry Andric     // Counter tracks the right hand side of a logical or operator.
14920b57cec5SDimitry Andric     extendRegion(E->getRHS());
14930b57cec5SDimitry Andric     propagateCounts(getRegionCounter(E), E->getRHS());
1494af732203SDimitry Andric 
1495af732203SDimitry Andric     // Extract the RHS's Execution Counter.
1496af732203SDimitry Andric     Counter RHSExecCnt = getRegionCounter(E);
1497af732203SDimitry Andric 
1498af732203SDimitry Andric     // Extract the RHS's "False" Instance Counter.
1499af732203SDimitry Andric     Counter RHSFalseCnt = getRegionCounter(E->getRHS());
1500af732203SDimitry Andric 
1501af732203SDimitry Andric     // Extract the Parent Region Counter.
1502af732203SDimitry Andric     Counter ParentCnt = getRegion().getCounter();
1503af732203SDimitry Andric 
1504af732203SDimitry Andric     // Create Branch Region around LHS condition.
1505af732203SDimitry Andric     createBranchRegion(E->getLHS(), subtractCounters(ParentCnt, RHSExecCnt),
1506af732203SDimitry Andric                        RHSExecCnt);
1507af732203SDimitry Andric 
1508af732203SDimitry Andric     // Create Branch Region around RHS condition.
1509af732203SDimitry Andric     createBranchRegion(E->getRHS(), subtractCounters(RHSExecCnt, RHSFalseCnt),
1510af732203SDimitry Andric                        RHSFalseCnt);
15110b57cec5SDimitry Andric   }
15120b57cec5SDimitry Andric 
VisitLambdaExpr__anone2f8b4240211::CounterCoverageMappingBuilder15130b57cec5SDimitry Andric   void VisitLambdaExpr(const LambdaExpr *LE) {
15140b57cec5SDimitry Andric     // Lambdas are treated as their own functions for now, so we shouldn't
15150b57cec5SDimitry Andric     // propagate counts into them.
15160b57cec5SDimitry Andric   }
15170b57cec5SDimitry Andric };
15180b57cec5SDimitry Andric 
15190b57cec5SDimitry Andric } // end anonymous namespace
15200b57cec5SDimitry Andric 
dump(llvm::raw_ostream & OS,StringRef FunctionName,ArrayRef<CounterExpression> Expressions,ArrayRef<CounterMappingRegion> Regions)15210b57cec5SDimitry Andric static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
15220b57cec5SDimitry Andric                  ArrayRef<CounterExpression> Expressions,
15230b57cec5SDimitry Andric                  ArrayRef<CounterMappingRegion> Regions) {
15240b57cec5SDimitry Andric   OS << FunctionName << ":\n";
15250b57cec5SDimitry Andric   CounterMappingContext Ctx(Expressions);
15260b57cec5SDimitry Andric   for (const auto &R : Regions) {
15270b57cec5SDimitry Andric     OS.indent(2);
15280b57cec5SDimitry Andric     switch (R.Kind) {
15290b57cec5SDimitry Andric     case CounterMappingRegion::CodeRegion:
15300b57cec5SDimitry Andric       break;
15310b57cec5SDimitry Andric     case CounterMappingRegion::ExpansionRegion:
15320b57cec5SDimitry Andric       OS << "Expansion,";
15330b57cec5SDimitry Andric       break;
15340b57cec5SDimitry Andric     case CounterMappingRegion::SkippedRegion:
15350b57cec5SDimitry Andric       OS << "Skipped,";
15360b57cec5SDimitry Andric       break;
15370b57cec5SDimitry Andric     case CounterMappingRegion::GapRegion:
15380b57cec5SDimitry Andric       OS << "Gap,";
15390b57cec5SDimitry Andric       break;
1540af732203SDimitry Andric     case CounterMappingRegion::BranchRegion:
1541af732203SDimitry Andric       OS << "Branch,";
1542af732203SDimitry Andric       break;
15430b57cec5SDimitry Andric     }
15440b57cec5SDimitry Andric 
15450b57cec5SDimitry Andric     OS << "File " << R.FileID << ", " << R.LineStart << ":" << R.ColumnStart
15460b57cec5SDimitry Andric        << " -> " << R.LineEnd << ":" << R.ColumnEnd << " = ";
15470b57cec5SDimitry Andric     Ctx.dump(R.Count, OS);
1548af732203SDimitry Andric 
1549af732203SDimitry Andric     if (R.Kind == CounterMappingRegion::BranchRegion) {
1550af732203SDimitry Andric       OS << ", ";
1551af732203SDimitry Andric       Ctx.dump(R.FalseCount, OS);
1552af732203SDimitry Andric     }
1553af732203SDimitry Andric 
15540b57cec5SDimitry Andric     if (R.Kind == CounterMappingRegion::ExpansionRegion)
15550b57cec5SDimitry Andric       OS << " (Expanded file = " << R.ExpandedFileID << ")";
15560b57cec5SDimitry Andric     OS << "\n";
15570b57cec5SDimitry Andric   }
15580b57cec5SDimitry Andric }
15590b57cec5SDimitry Andric 
CoverageMappingModuleGen(CodeGenModule & CGM,CoverageSourceInfo & SourceInfo)1560af732203SDimitry Andric CoverageMappingModuleGen::CoverageMappingModuleGen(
1561af732203SDimitry Andric     CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
1562af732203SDimitry Andric     : CGM(CGM), SourceInfo(SourceInfo) {
1563*5f7ddb14SDimitry Andric   CoveragePrefixMap = CGM.getCodeGenOpts().CoveragePrefixMap;
1564*5f7ddb14SDimitry Andric }
1565*5f7ddb14SDimitry Andric 
getCurrentDirname()1566*5f7ddb14SDimitry Andric std::string CoverageMappingModuleGen::getCurrentDirname() {
1567*5f7ddb14SDimitry Andric   if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
1568*5f7ddb14SDimitry Andric     return CGM.getCodeGenOpts().CoverageCompilationDir;
1569*5f7ddb14SDimitry Andric 
1570*5f7ddb14SDimitry Andric   SmallString<256> CWD;
1571*5f7ddb14SDimitry Andric   llvm::sys::fs::current_path(CWD);
1572*5f7ddb14SDimitry Andric   return CWD.str().str();
1573af732203SDimitry Andric }
1574af732203SDimitry Andric 
normalizeFilename(StringRef Filename)1575af732203SDimitry Andric std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
1576af732203SDimitry Andric   llvm::SmallString<256> Path(Filename);
1577af732203SDimitry Andric   llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
1578*5f7ddb14SDimitry Andric   for (const auto &Entry : CoveragePrefixMap) {
1579af732203SDimitry Andric     if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
1580af732203SDimitry Andric       break;
1581af732203SDimitry Andric   }
1582af732203SDimitry Andric   return Path.str().str();
1583af732203SDimitry Andric }
1584af732203SDimitry Andric 
getInstrProfSection(const CodeGenModule & CGM,llvm::InstrProfSectKind SK)15855ffd83dbSDimitry Andric static std::string getInstrProfSection(const CodeGenModule &CGM,
15865ffd83dbSDimitry Andric                                        llvm::InstrProfSectKind SK) {
15875ffd83dbSDimitry Andric   return llvm::getInstrProfSectionName(
15885ffd83dbSDimitry Andric       SK, CGM.getContext().getTargetInfo().getTriple().getObjectFormat());
15895ffd83dbSDimitry Andric }
15905ffd83dbSDimitry Andric 
emitFunctionMappingRecord(const FunctionInfo & Info,uint64_t FilenamesRef)15915ffd83dbSDimitry Andric void CoverageMappingModuleGen::emitFunctionMappingRecord(
15925ffd83dbSDimitry Andric     const FunctionInfo &Info, uint64_t FilenamesRef) {
15930b57cec5SDimitry Andric   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
15945ffd83dbSDimitry Andric 
15955ffd83dbSDimitry Andric   // Assign a name to the function record. This is used to merge duplicates.
15965ffd83dbSDimitry Andric   std::string FuncRecordName = "__covrec_" + llvm::utohexstr(Info.NameHash);
15975ffd83dbSDimitry Andric 
15985ffd83dbSDimitry Andric   // A dummy description for a function included-but-not-used in a TU can be
15995ffd83dbSDimitry Andric   // replaced by full description provided by a different TU. The two kinds of
16005ffd83dbSDimitry Andric   // descriptions play distinct roles: therefore, assign them different names
16015ffd83dbSDimitry Andric   // to prevent `linkonce_odr` merging.
16025ffd83dbSDimitry Andric   if (Info.IsUsed)
16035ffd83dbSDimitry Andric     FuncRecordName += "u";
16045ffd83dbSDimitry Andric 
16055ffd83dbSDimitry Andric   // Create the function record type.
16065ffd83dbSDimitry Andric   const uint64_t NameHash = Info.NameHash;
16075ffd83dbSDimitry Andric   const uint64_t FuncHash = Info.FuncHash;
16085ffd83dbSDimitry Andric   const std::string &CoverageMapping = Info.CoverageMapping;
16090b57cec5SDimitry Andric #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) LLVMType,
16100b57cec5SDimitry Andric   llvm::Type *FunctionRecordTypes[] = {
16110b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
16120b57cec5SDimitry Andric   };
16135ffd83dbSDimitry Andric   auto *FunctionRecordTy =
16140b57cec5SDimitry Andric       llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes),
16150b57cec5SDimitry Andric                             /*isPacked=*/true);
16160b57cec5SDimitry Andric 
16175ffd83dbSDimitry Andric   // Create the function record constant.
16180b57cec5SDimitry Andric #define COVMAP_FUNC_RECORD(Type, LLVMType, Name, Init) Init,
16190b57cec5SDimitry Andric   llvm::Constant *FunctionRecordVals[] = {
16200b57cec5SDimitry Andric       #include "llvm/ProfileData/InstrProfData.inc"
16210b57cec5SDimitry Andric   };
16225ffd83dbSDimitry Andric   auto *FuncRecordConstant = llvm::ConstantStruct::get(
16235ffd83dbSDimitry Andric       FunctionRecordTy, makeArrayRef(FunctionRecordVals));
16245ffd83dbSDimitry Andric 
16255ffd83dbSDimitry Andric   // Create the function record global.
16265ffd83dbSDimitry Andric   auto *FuncRecord = new llvm::GlobalVariable(
16275ffd83dbSDimitry Andric       CGM.getModule(), FunctionRecordTy, /*isConstant=*/true,
16285ffd83dbSDimitry Andric       llvm::GlobalValue::LinkOnceODRLinkage, FuncRecordConstant,
16295ffd83dbSDimitry Andric       FuncRecordName);
16305ffd83dbSDimitry Andric   FuncRecord->setVisibility(llvm::GlobalValue::HiddenVisibility);
16315ffd83dbSDimitry Andric   FuncRecord->setSection(getInstrProfSection(CGM, llvm::IPSK_covfun));
16325ffd83dbSDimitry Andric   FuncRecord->setAlignment(llvm::Align(8));
16335ffd83dbSDimitry Andric   if (CGM.supportsCOMDAT())
16345ffd83dbSDimitry Andric     FuncRecord->setComdat(CGM.getModule().getOrInsertComdat(FuncRecordName));
16355ffd83dbSDimitry Andric 
16365ffd83dbSDimitry Andric   // Make sure the data doesn't get deleted.
16375ffd83dbSDimitry Andric   CGM.addUsedGlobal(FuncRecord);
16385ffd83dbSDimitry Andric }
16395ffd83dbSDimitry Andric 
addFunctionMappingRecord(llvm::GlobalVariable * NamePtr,StringRef NameValue,uint64_t FuncHash,const std::string & CoverageMapping,bool IsUsed)16405ffd83dbSDimitry Andric void CoverageMappingModuleGen::addFunctionMappingRecord(
16415ffd83dbSDimitry Andric     llvm::GlobalVariable *NamePtr, StringRef NameValue, uint64_t FuncHash,
16425ffd83dbSDimitry Andric     const std::string &CoverageMapping, bool IsUsed) {
16435ffd83dbSDimitry Andric   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
16445ffd83dbSDimitry Andric   const uint64_t NameHash = llvm::IndexedInstrProf::ComputeHash(NameValue);
16455ffd83dbSDimitry Andric   FunctionRecords.push_back({NameHash, FuncHash, CoverageMapping, IsUsed});
16465ffd83dbSDimitry Andric 
16470b57cec5SDimitry Andric   if (!IsUsed)
16480b57cec5SDimitry Andric     FunctionNames.push_back(
16490b57cec5SDimitry Andric         llvm::ConstantExpr::getBitCast(NamePtr, llvm::Type::getInt8PtrTy(Ctx)));
16500b57cec5SDimitry Andric 
16510b57cec5SDimitry Andric   if (CGM.getCodeGenOpts().DumpCoverageMapping) {
16520b57cec5SDimitry Andric     // Dump the coverage mapping data for this function by decoding the
16530b57cec5SDimitry Andric     // encoded data. This allows us to dump the mapping regions which were
16540b57cec5SDimitry Andric     // also processed by the CoverageMappingWriter which performs
16550b57cec5SDimitry Andric     // additional minimization operations such as reducing the number of
16560b57cec5SDimitry Andric     // expressions.
1657*5f7ddb14SDimitry Andric     llvm::SmallVector<std::string, 16> FilenameStrs;
16580b57cec5SDimitry Andric     std::vector<StringRef> Filenames;
16590b57cec5SDimitry Andric     std::vector<CounterExpression> Expressions;
16600b57cec5SDimitry Andric     std::vector<CounterMappingRegion> Regions;
1661*5f7ddb14SDimitry Andric     FilenameStrs.resize(FileEntries.size() + 1);
1662*5f7ddb14SDimitry Andric     FilenameStrs[0] = normalizeFilename(getCurrentDirname());
16630b57cec5SDimitry Andric     for (const auto &Entry : FileEntries) {
16640b57cec5SDimitry Andric       auto I = Entry.second;
16650b57cec5SDimitry Andric       FilenameStrs[I] = normalizeFilename(Entry.first->getName());
16660b57cec5SDimitry Andric     }
1667*5f7ddb14SDimitry Andric     ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(FilenameStrs);
16680b57cec5SDimitry Andric     RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
16690b57cec5SDimitry Andric                                     Expressions, Regions);
16700b57cec5SDimitry Andric     if (Reader.read())
16710b57cec5SDimitry Andric       return;
16720b57cec5SDimitry Andric     dump(llvm::outs(), NameValue, Expressions, Regions);
16730b57cec5SDimitry Andric   }
16740b57cec5SDimitry Andric }
16750b57cec5SDimitry Andric 
emit()16760b57cec5SDimitry Andric void CoverageMappingModuleGen::emit() {
16770b57cec5SDimitry Andric   if (FunctionRecords.empty())
16780b57cec5SDimitry Andric     return;
16790b57cec5SDimitry Andric   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
16800b57cec5SDimitry Andric   auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric   // Create the filenames and merge them with coverage mappings
16830b57cec5SDimitry Andric   llvm::SmallVector<std::string, 16> FilenameStrs;
1684*5f7ddb14SDimitry Andric   FilenameStrs.resize(FileEntries.size() + 1);
1685*5f7ddb14SDimitry Andric   // The first filename is the current working directory.
1686*5f7ddb14SDimitry Andric   FilenameStrs[0] = normalizeFilename(getCurrentDirname());
16870b57cec5SDimitry Andric   for (const auto &Entry : FileEntries) {
16880b57cec5SDimitry Andric     auto I = Entry.second;
16890b57cec5SDimitry Andric     FilenameStrs[I] = normalizeFilename(Entry.first->getName());
16900b57cec5SDimitry Andric   }
16910b57cec5SDimitry Andric 
16925ffd83dbSDimitry Andric   std::string Filenames;
16935ffd83dbSDimitry Andric   {
16945ffd83dbSDimitry Andric     llvm::raw_string_ostream OS(Filenames);
1695*5f7ddb14SDimitry Andric     CoverageFilenamesSectionWriter(FilenameStrs).write(OS);
16960b57cec5SDimitry Andric   }
16975ffd83dbSDimitry Andric   auto *FilenamesVal =
16985ffd83dbSDimitry Andric       llvm::ConstantDataArray::getString(Ctx, Filenames, false);
16995ffd83dbSDimitry Andric   const int64_t FilenamesRef = llvm::IndexedInstrProf::ComputeHash(Filenames);
17000b57cec5SDimitry Andric 
17015ffd83dbSDimitry Andric   // Emit the function records.
17025ffd83dbSDimitry Andric   for (const FunctionInfo &Info : FunctionRecords)
17035ffd83dbSDimitry Andric     emitFunctionMappingRecord(Info, FilenamesRef);
17040b57cec5SDimitry Andric 
17055ffd83dbSDimitry Andric   const unsigned NRecords = 0;
17065ffd83dbSDimitry Andric   const size_t FilenamesSize = Filenames.size();
17075ffd83dbSDimitry Andric   const unsigned CoverageMappingSize = 0;
17080b57cec5SDimitry Andric   llvm::Type *CovDataHeaderTypes[] = {
17090b57cec5SDimitry Andric #define COVMAP_HEADER(Type, LLVMType, Name, Init) LLVMType,
17100b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
17110b57cec5SDimitry Andric   };
17120b57cec5SDimitry Andric   auto CovDataHeaderTy =
17130b57cec5SDimitry Andric       llvm::StructType::get(Ctx, makeArrayRef(CovDataHeaderTypes));
17140b57cec5SDimitry Andric   llvm::Constant *CovDataHeaderVals[] = {
17150b57cec5SDimitry Andric #define COVMAP_HEADER(Type, LLVMType, Name, Init) Init,
17160b57cec5SDimitry Andric #include "llvm/ProfileData/InstrProfData.inc"
17170b57cec5SDimitry Andric   };
17180b57cec5SDimitry Andric   auto CovDataHeaderVal = llvm::ConstantStruct::get(
17190b57cec5SDimitry Andric       CovDataHeaderTy, makeArrayRef(CovDataHeaderVals));
17200b57cec5SDimitry Andric 
17210b57cec5SDimitry Andric   // Create the coverage data record
17225ffd83dbSDimitry Andric   llvm::Type *CovDataTypes[] = {CovDataHeaderTy, FilenamesVal->getType()};
17230b57cec5SDimitry Andric   auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
17245ffd83dbSDimitry Andric   llvm::Constant *TUDataVals[] = {CovDataHeaderVal, FilenamesVal};
17250b57cec5SDimitry Andric   auto CovDataVal =
17260b57cec5SDimitry Andric       llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
17270b57cec5SDimitry Andric   auto CovData = new llvm::GlobalVariable(
17285ffd83dbSDimitry Andric       CGM.getModule(), CovDataTy, true, llvm::GlobalValue::PrivateLinkage,
17290b57cec5SDimitry Andric       CovDataVal, llvm::getCoverageMappingVarName());
17300b57cec5SDimitry Andric 
17315ffd83dbSDimitry Andric   CovData->setSection(getInstrProfSection(CGM, llvm::IPSK_covmap));
1732a7dea167SDimitry Andric   CovData->setAlignment(llvm::Align(8));
17330b57cec5SDimitry Andric 
17340b57cec5SDimitry Andric   // Make sure the data doesn't get deleted.
17350b57cec5SDimitry Andric   CGM.addUsedGlobal(CovData);
17360b57cec5SDimitry Andric   // Create the deferred function records array
17370b57cec5SDimitry Andric   if (!FunctionNames.empty()) {
17380b57cec5SDimitry Andric     auto NamesArrTy = llvm::ArrayType::get(llvm::Type::getInt8PtrTy(Ctx),
17390b57cec5SDimitry Andric                                            FunctionNames.size());
17400b57cec5SDimitry Andric     auto NamesArrVal = llvm::ConstantArray::get(NamesArrTy, FunctionNames);
17410b57cec5SDimitry Andric     // This variable will *NOT* be emitted to the object file. It is used
17420b57cec5SDimitry Andric     // to pass the list of names referenced to codegen.
17430b57cec5SDimitry Andric     new llvm::GlobalVariable(CGM.getModule(), NamesArrTy, true,
17440b57cec5SDimitry Andric                              llvm::GlobalValue::InternalLinkage, NamesArrVal,
17450b57cec5SDimitry Andric                              llvm::getCoverageUnusedNamesVarName());
17460b57cec5SDimitry Andric   }
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric 
getFileID(const FileEntry * File)17490b57cec5SDimitry Andric unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
17500b57cec5SDimitry Andric   auto It = FileEntries.find(File);
17510b57cec5SDimitry Andric   if (It != FileEntries.end())
17520b57cec5SDimitry Andric     return It->second;
1753*5f7ddb14SDimitry Andric   unsigned FileID = FileEntries.size() + 1;
17540b57cec5SDimitry Andric   FileEntries.insert(std::make_pair(File, FileID));
17550b57cec5SDimitry Andric   return FileID;
17560b57cec5SDimitry Andric }
17570b57cec5SDimitry Andric 
emitCounterMapping(const Decl * D,llvm::raw_ostream & OS)17580b57cec5SDimitry Andric void CoverageMappingGen::emitCounterMapping(const Decl *D,
17590b57cec5SDimitry Andric                                             llvm::raw_ostream &OS) {
17600b57cec5SDimitry Andric   assert(CounterMap);
17610b57cec5SDimitry Andric   CounterCoverageMappingBuilder Walker(CVM, *CounterMap, SM, LangOpts);
17620b57cec5SDimitry Andric   Walker.VisitDecl(D);
17630b57cec5SDimitry Andric   Walker.write(OS);
17640b57cec5SDimitry Andric }
17650b57cec5SDimitry Andric 
emitEmptyMapping(const Decl * D,llvm::raw_ostream & OS)17660b57cec5SDimitry Andric void CoverageMappingGen::emitEmptyMapping(const Decl *D,
17670b57cec5SDimitry Andric                                           llvm::raw_ostream &OS) {
17680b57cec5SDimitry Andric   EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
17690b57cec5SDimitry Andric   Walker.VisitDecl(D);
17700b57cec5SDimitry Andric   Walker.write(OS);
17710b57cec5SDimitry Andric }
1772