1167 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			1167 lines
		
	
	
		
			43 KiB
		
	
	
	
		
			C++
		
	
	
	
//===--- CoverageMappingGen.cpp - Coverage mapping generation ---*- C++ -*-===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// Instrumentation-based code coverage mapping generator
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "CoverageMappingGen.h"
 | 
						|
#include "CodeGenFunction.h"
 | 
						|
#include "clang/AST/StmtVisitor.h"
 | 
						|
#include "clang/Lex/Lexer.h"
 | 
						|
#include "llvm/ProfileData/InstrProfReader.h"
 | 
						|
#include "llvm/ProfileData/CoverageMapping.h"
 | 
						|
#include "llvm/ProfileData/CoverageMappingWriter.h"
 | 
						|
#include "llvm/Support/FileSystem.h"
 | 
						|
 | 
						|
using namespace clang;
 | 
						|
using namespace CodeGen;
 | 
						|
using namespace llvm::coverage;
 | 
						|
 | 
						|
void CoverageSourceInfo::SourceRangeSkipped(SourceRange Range) {
 | 
						|
  SkippedRanges.push_back(Range);
 | 
						|
}
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
/// \brief A region of source code that can be mapped to a counter.
 | 
						|
struct SourceMappingRegion {
 | 
						|
  enum RegionFlags {
 | 
						|
    /// \brief This region won't be emitted if it wasn't extended.
 | 
						|
    /// This is useful so that we won't emit source ranges for single tokens
 | 
						|
    /// that we don't really care that much about, like:
 | 
						|
    ///   the '(' token in #define MACRO (
 | 
						|
    IgnoreIfNotExtended = 0x0001,
 | 
						|
  };
 | 
						|
 | 
						|
  FileID File, MacroArgumentFile;
 | 
						|
 | 
						|
  Counter Count;
 | 
						|
 | 
						|
  /// \brief A statement that initiated the count of Zero.
 | 
						|
  ///
 | 
						|
  /// This initiator statement is useful to prevent merging of unreachable
 | 
						|
  /// regions with different statements that caused the counter to become
 | 
						|
  /// unreachable.
 | 
						|
  const Stmt *UnreachableInitiator;
 | 
						|
 | 
						|
  /// \brief A statement that separates certain mapping regions into groups.
 | 
						|
  ///
 | 
						|
  /// The group statement is sometimes useful when we are emitting the source
 | 
						|
  /// regions not in their correct lexical order, e.g. the regions for the
 | 
						|
  /// incrementation expression in the 'for' construct. By marking the regions
 | 
						|
  /// in the incrementation expression with the group statement, we avoid the
 | 
						|
  /// merging of the regions from the incrementation expression and the loop's
 | 
						|
  /// body.
 | 
						|
  const Stmt *Group;
 | 
						|
 | 
						|
  /// \brief The region's starting location.
 | 
						|
  SourceLocation LocStart;
 | 
						|
 | 
						|
  /// \brief The region's ending location.
 | 
						|
  SourceLocation LocEnd, AlternativeLocEnd;
 | 
						|
  unsigned Flags;
 | 
						|
  CounterMappingRegion::RegionKind Kind;
 | 
						|
 | 
						|
  SourceMappingRegion(FileID File, FileID MacroArgumentFile, Counter Count,
 | 
						|
                      const Stmt *UnreachableInitiator, const Stmt *Group,
 | 
						|
                      SourceLocation LocStart, SourceLocation LocEnd,
 | 
						|
                      unsigned Flags = 0,
 | 
						|
                      CounterMappingRegion::RegionKind Kind =
 | 
						|
                          CounterMappingRegion::CodeRegion)
 | 
						|
      : File(File), MacroArgumentFile(MacroArgumentFile), Count(Count),
 | 
						|
        UnreachableInitiator(UnreachableInitiator), Group(Group),
 | 
						|
        LocStart(LocStart), LocEnd(LocEnd), AlternativeLocEnd(LocStart),
 | 
						|
        Flags(Flags), Kind(Kind) {}
 | 
						|
 | 
						|
  bool hasFlag(RegionFlags Flag) const { return (Flags & Flag) != 0; }
 | 
						|
 | 
						|
  void setFlag(RegionFlags Flag) { Flags |= Flag; }
 | 
						|
 | 
						|
  void clearFlag(RegionFlags Flag) { Flags &= ~Flag; }
 | 
						|
 | 
						|
  /// \brief Return true if two regions can be merged together.
 | 
						|
  bool isMergeable(SourceMappingRegion &R) {
 | 
						|
    return File == R.File && MacroArgumentFile == R.MacroArgumentFile &&
 | 
						|
           Count == R.Count && UnreachableInitiator == R.UnreachableInitiator &&
 | 
						|
           Group == R.Group && Kind == R.Kind;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Merge two regions by extending the 'this' region to cover the
 | 
						|
  /// given region.
 | 
						|
  void mergeByExtendingTo(SourceMappingRegion &R) {
 | 
						|
    LocEnd = R.LocEnd;
 | 
						|
    AlternativeLocEnd = R.LocStart;
 | 
						|
    if (hasFlag(IgnoreIfNotExtended))
 | 
						|
      clearFlag(IgnoreIfNotExtended);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/// \brief The state of the coverage mapping builder.
 | 
						|
struct SourceMappingState {
 | 
						|
  Counter CurrentRegionCount;
 | 
						|
  const Stmt *CurrentSourceGroup;
 | 
						|
  const Stmt *CurrentUnreachableRegionInitiator;
 | 
						|
 | 
						|
  SourceMappingState(Counter CurrentRegionCount, const Stmt *CurrentSourceGroup,
 | 
						|
                     const Stmt *CurrentUnreachableRegionInitiator)
 | 
						|
      : CurrentRegionCount(CurrentRegionCount),
 | 
						|
        CurrentSourceGroup(CurrentSourceGroup),
 | 
						|
        CurrentUnreachableRegionInitiator(CurrentUnreachableRegionInitiator) {}
 | 
						|
};
 | 
						|
 | 
						|
/// \brief Provides the common functionality for the different
 | 
						|
/// coverage mapping region builders.
 | 
						|
class CoverageMappingBuilder {
 | 
						|
public:
 | 
						|
  CoverageMappingModuleGen &CVM;
 | 
						|
  SourceManager &SM;
 | 
						|
  const LangOptions &LangOpts;
 | 
						|
 | 
						|
private:
 | 
						|
  struct FileInfo {
 | 
						|
    /// \brief The file id that will be used by the coverage mapping system.
 | 
						|
    unsigned CovMappingFileID;
 | 
						|
    const FileEntry *Entry;
 | 
						|
 | 
						|
    FileInfo(unsigned CovMappingFileID, const FileEntry *Entry)
 | 
						|
        : CovMappingFileID(CovMappingFileID), Entry(Entry) {}
 | 
						|
  };
 | 
						|
 | 
						|
  /// \brief This mapping maps clang's FileIDs to file ids used
 | 
						|
  /// by the coverage mapping system and clang's file entries.
 | 
						|
  llvm::SmallDenseMap<FileID, FileInfo, 8> FileIDMapping;
 | 
						|
 | 
						|
public:
 | 
						|
  /// \brief The statement that corresponds to the current source group.
 | 
						|
  const Stmt *CurrentSourceGroup;
 | 
						|
 | 
						|
  /// \brief The statement the initiated the current unreachable region.
 | 
						|
  const Stmt *CurrentUnreachableRegionInitiator;
 | 
						|
 | 
						|
  /// \brief The coverage mapping regions for this function
 | 
						|
  llvm::SmallVector<CounterMappingRegion, 32> MappingRegions;
 | 
						|
  /// \brief The source mapping regions for this function.
 | 
						|
  llvm::SmallVector<SourceMappingRegion, 32> SourceRegions;
 | 
						|
 | 
						|
  CoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
 | 
						|
                         const LangOptions &LangOpts)
 | 
						|
      : CVM(CVM), SM(SM), LangOpts(LangOpts),
 | 
						|
        CurrentSourceGroup(nullptr),
 | 
						|
        CurrentUnreachableRegionInitiator(nullptr) {}
 | 
						|
 | 
						|
  /// \brief Return the precise end location for the given token.
 | 
						|
  SourceLocation getPreciseTokenLocEnd(SourceLocation Loc) {
 | 
						|
    return Lexer::getLocForEndOfToken(SM.getSpellingLoc(Loc), 0, SM, LangOpts);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Create the mapping that maps from the function's file ids to
 | 
						|
  /// the indices for the translation unit's filenames.
 | 
						|
  void createFileIDMapping(SmallVectorImpl<unsigned> &Mapping) {
 | 
						|
    Mapping.resize(FileIDMapping.size(), 0);
 | 
						|
    for (const auto &I : FileIDMapping)
 | 
						|
      Mapping[I.second.CovMappingFileID] = CVM.getFileID(I.second.Entry);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Get the coverage mapping file id that corresponds to the given
 | 
						|
  /// clang file id. If such file id doesn't exist, it gets added to the
 | 
						|
  /// mapping that maps from clang's file ids to coverage mapping file ids.
 | 
						|
  /// Return true if there was an error getting the coverage mapping file id.
 | 
						|
  /// An example of an when this function fails is when the region tries
 | 
						|
  /// to get a coverage file id for a location in a built-in macro.
 | 
						|
  bool getCoverageFileID(SourceLocation LocStart, FileID File,
 | 
						|
                         FileID SpellingFile, unsigned &Result) {
 | 
						|
    auto Mapping = FileIDMapping.find(File);
 | 
						|
    if (Mapping != FileIDMapping.end()) {
 | 
						|
      Result = Mapping->second.CovMappingFileID;
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
 | 
						|
    auto Entry = SM.getFileEntryForID(SpellingFile);
 | 
						|
    if (!Entry)
 | 
						|
      return true;
 | 
						|
 | 
						|
    Result = FileIDMapping.size();
 | 
						|
    FileIDMapping.insert(std::make_pair(File, FileInfo(Result, Entry)));
 | 
						|
    createFileExpansionRegion(LocStart, File);
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Get the coverage mapping file id that corresponds to the given
 | 
						|
  /// clang file id.
 | 
						|
  /// Return true if there was an error getting the coverage mapping file id.
 | 
						|
  bool getExistingCoverageFileID(FileID File, unsigned &Result) {
 | 
						|
    // Make sure that the file is valid.
 | 
						|
    if (File.isInvalid())
 | 
						|
      return true;
 | 
						|
    auto Mapping = FileIDMapping.find(File);
 | 
						|
    if (Mapping != FileIDMapping.end()) {
 | 
						|
      Result = Mapping->second.CovMappingFileID;
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Return true if the given clang's file id has a corresponding
 | 
						|
  /// coverage file id.
 | 
						|
  bool hasExistingCoverageFileID(FileID File) const {
 | 
						|
    return FileIDMapping.count(File);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Gather all the regions that were skipped by the preprocessor
 | 
						|
  /// using the constructs like #if.
 | 
						|
  void gatherSkippedRegions() {
 | 
						|
    /// An array of the minimum lineStarts and the maximum lineEnds
 | 
						|
    /// for mapping regions from the appropriate source files.
 | 
						|
    llvm::SmallVector<std::pair<unsigned, unsigned>, 8> FileLineRanges;
 | 
						|
    FileLineRanges.resize(
 | 
						|
        FileIDMapping.size(),
 | 
						|
        std::make_pair(std::numeric_limits<unsigned>::max(), 0));
 | 
						|
    for (const auto &R : MappingRegions) {
 | 
						|
      FileLineRanges[R.FileID].first =
 | 
						|
          std::min(FileLineRanges[R.FileID].first, R.LineStart);
 | 
						|
      FileLineRanges[R.FileID].second =
 | 
						|
          std::max(FileLineRanges[R.FileID].second, R.LineEnd);
 | 
						|
    }
 | 
						|
 | 
						|
    auto SkippedRanges = CVM.getSourceInfo().getSkippedRanges();
 | 
						|
    for (const auto &I : SkippedRanges) {
 | 
						|
      auto LocStart = I.getBegin();
 | 
						|
      auto LocEnd = I.getEnd();
 | 
						|
      auto FileStart = SM.getFileID(LocStart);
 | 
						|
      if (!hasExistingCoverageFileID(FileStart))
 | 
						|
        continue;
 | 
						|
      auto ActualFileStart = SM.getDecomposedSpellingLoc(LocStart).first;
 | 
						|
      if (ActualFileStart != SM.getDecomposedSpellingLoc(LocEnd).first)
 | 
						|
        // Ignore regions that span across multiple files.
 | 
						|
        continue;
 | 
						|
 | 
						|
      unsigned CovFileID;
 | 
						|
      if (getCoverageFileID(LocStart, FileStart, ActualFileStart, CovFileID))
 | 
						|
        continue;
 | 
						|
      unsigned LineStart = SM.getSpellingLineNumber(LocStart);
 | 
						|
      unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
 | 
						|
      unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
 | 
						|
      unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
 | 
						|
      CounterMappingRegion Region(Counter(), CovFileID, LineStart, ColumnStart,
 | 
						|
                                  LineEnd, ColumnEnd, false,
 | 
						|
                                  CounterMappingRegion::SkippedRegion);
 | 
						|
      // Make sure that we only collect the regions that are inside
 | 
						|
      // the souce code of this function.
 | 
						|
      if (Region.LineStart >= FileLineRanges[CovFileID].first &&
 | 
						|
          Region.LineEnd <= FileLineRanges[CovFileID].second)
 | 
						|
        MappingRegions.push_back(Region);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Create a mapping region that correponds to an expansion of
 | 
						|
  /// a macro or an embedded include.
 | 
						|
  void createFileExpansionRegion(SourceLocation Loc, FileID ExpandedFile) {
 | 
						|
    SourceLocation LocStart;
 | 
						|
    if (Loc.isMacroID())
 | 
						|
      LocStart = SM.getImmediateExpansionRange(Loc).first;
 | 
						|
    else {
 | 
						|
      LocStart = SM.getIncludeLoc(ExpandedFile);
 | 
						|
      if (LocStart.isInvalid())
 | 
						|
        return; // This file has no expansion region.
 | 
						|
    }
 | 
						|
 | 
						|
    auto File = SM.getFileID(LocStart);
 | 
						|
    auto SpellingFile = SM.getDecomposedSpellingLoc(LocStart).first;
 | 
						|
    unsigned CovFileID, ExpandedFileID;
 | 
						|
    if (getExistingCoverageFileID(ExpandedFile, ExpandedFileID))
 | 
						|
      return;
 | 
						|
    if (getCoverageFileID(LocStart, File, SpellingFile, CovFileID))
 | 
						|
      return;
 | 
						|
    unsigned LineStart = SM.getSpellingLineNumber(LocStart);
 | 
						|
    unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
 | 
						|
    unsigned LineEnd = LineStart;
 | 
						|
    // Compute the end column manually as Lexer::getLocForEndOfToken doesn't
 | 
						|
    // give the correct result in all cases.
 | 
						|
    unsigned ColumnEnd =
 | 
						|
        ColumnStart +
 | 
						|
        Lexer::MeasureTokenLength(SM.getSpellingLoc(LocStart), SM, LangOpts);
 | 
						|
 | 
						|
    MappingRegions.push_back(CounterMappingRegion(
 | 
						|
        Counter(), CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd,
 | 
						|
        false, CounterMappingRegion::ExpansionRegion));
 | 
						|
    MappingRegions.back().ExpandedFileID = ExpandedFileID;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Enter a source region group that is identified by the given
 | 
						|
  /// statement.
 | 
						|
  /// It's not possible to enter a group when there is already
 | 
						|
  /// another group present.
 | 
						|
  void beginSourceRegionGroup(const Stmt *Group) {
 | 
						|
    assert(!CurrentSourceGroup);
 | 
						|
    CurrentSourceGroup = Group;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Exit the current source region group.
 | 
						|
  void endSourceRegionGroup() { CurrentSourceGroup = nullptr; }
 | 
						|
 | 
						|
  /// \brief Brings a region that has the same counter and file to the back
 | 
						|
  /// of the source regions array.
 | 
						|
  void bringSimilarRegionBack(Counter Count, FileID File,
 | 
						|
                              FileID MacroArgumentFile,
 | 
						|
                              const Stmt *UnreachableInitiator,
 | 
						|
                              const Stmt *SourceGroup) {
 | 
						|
    for (size_t I = SourceRegions.size(); I != 0;) {
 | 
						|
      --I;
 | 
						|
      if (SourceRegions[I].Count == Count && SourceRegions[I].File == File &&
 | 
						|
          SourceRegions[I].MacroArgumentFile == MacroArgumentFile &&
 | 
						|
          SourceRegions[I].UnreachableInitiator == UnreachableInitiator &&
 | 
						|
          SourceRegions[I].Group == SourceGroup) {
 | 
						|
        if (I != SourceRegions.size() - 1)
 | 
						|
          std::swap(SourceRegions[I], SourceRegions.back());
 | 
						|
        return;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Associate a counter with a given source code range.
 | 
						|
  void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
 | 
						|
                          Counter Count, const Stmt *UnreachableInitiator,
 | 
						|
                          const Stmt *SourceGroup, unsigned Flags = 0,
 | 
						|
                          FileID MacroArgumentFile = FileID()) {
 | 
						|
    if (SM.isMacroArgExpansion(LocStart)) {
 | 
						|
      // Map the code range with the macro argument's value.
 | 
						|
      mapSourceCodeRange(SM.getImmediateSpellingLoc(LocStart),
 | 
						|
                         SM.getImmediateSpellingLoc(LocEnd), Count,
 | 
						|
                         UnreachableInitiator, SourceGroup, Flags,
 | 
						|
                         SM.getFileID(LocStart));
 | 
						|
      // Map the code range where the macro argument is referenced.
 | 
						|
      SourceLocation RefLocStart(SM.getImmediateExpansionRange(LocStart).first);
 | 
						|
      SourceLocation RefLocEnd(RefLocStart);
 | 
						|
      if (SM.isMacroArgExpansion(RefLocStart))
 | 
						|
        mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
 | 
						|
                           SourceGroup, 0, SM.getFileID(RefLocStart));
 | 
						|
      else
 | 
						|
        mapSourceCodeRange(RefLocStart, RefLocEnd, Count, UnreachableInitiator,
 | 
						|
                           SourceGroup);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    auto File = SM.getFileID(LocStart);
 | 
						|
    // Make sure that the file id is valid.
 | 
						|
    if (File.isInvalid())
 | 
						|
      return;
 | 
						|
    bringSimilarRegionBack(Count, File, MacroArgumentFile, UnreachableInitiator,
 | 
						|
                           SourceGroup);
 | 
						|
    SourceMappingRegion R(File, MacroArgumentFile, Count, UnreachableInitiator,
 | 
						|
                          SourceGroup, LocStart, LocEnd, Flags);
 | 
						|
    if (SourceRegions.empty() || !SourceRegions.back().isMergeable(R)) {
 | 
						|
      SourceRegions.push_back(R);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    SourceRegions.back().mergeByExtendingTo(R);
 | 
						|
  }
 | 
						|
 | 
						|
  void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
 | 
						|
                          Counter Count, unsigned Flags = 0) {
 | 
						|
    mapSourceCodeRange(LocStart, LocEnd, Count,
 | 
						|
                       CurrentUnreachableRegionInitiator, CurrentSourceGroup,
 | 
						|
                       Flags);
 | 
						|
  }
 | 
						|
 | 
						|
  void mapSourceCodeRange(const SourceMappingState &State,
 | 
						|
                          SourceLocation LocStart, SourceLocation LocEnd,
 | 
						|
                          unsigned Flags = 0) {
 | 
						|
    mapSourceCodeRange(LocStart, LocEnd, State.CurrentRegionCount,
 | 
						|
                       State.CurrentUnreachableRegionInitiator,
 | 
						|
                       State.CurrentSourceGroup, Flags);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Generate the coverage counter mapping regions from collected
 | 
						|
  /// source regions.
 | 
						|
  void emitSourceRegions() {
 | 
						|
    for (const auto &R : SourceRegions) {
 | 
						|
      SourceLocation LocStart = R.LocStart;
 | 
						|
      SourceLocation LocEnd = R.LocEnd;
 | 
						|
      if (SM.getFileID(LocEnd) != R.File)
 | 
						|
        LocEnd = R.AlternativeLocEnd;
 | 
						|
 | 
						|
      if (R.hasFlag(SourceMappingRegion::IgnoreIfNotExtended) &&
 | 
						|
          LocStart == LocEnd)
 | 
						|
        continue;
 | 
						|
 | 
						|
      LocEnd = getPreciseTokenLocEnd(LocEnd);
 | 
						|
      unsigned LineStart = SM.getSpellingLineNumber(LocStart);
 | 
						|
      unsigned ColumnStart = SM.getSpellingColumnNumber(LocStart);
 | 
						|
      unsigned LineEnd = SM.getSpellingLineNumber(LocEnd);
 | 
						|
      unsigned ColumnEnd = SM.getSpellingColumnNumber(LocEnd);
 | 
						|
 | 
						|
      auto SpellingFile = SM.getDecomposedSpellingLoc(R.LocStart).first;
 | 
						|
      unsigned CovFileID;
 | 
						|
      if (getCoverageFileID(R.LocStart, R.File, SpellingFile, CovFileID))
 | 
						|
        continue;
 | 
						|
 | 
						|
      assert(LineStart <= LineEnd);
 | 
						|
      MappingRegions.push_back(CounterMappingRegion(
 | 
						|
          R.Count, CovFileID, LineStart, ColumnStart, LineEnd, ColumnEnd,
 | 
						|
          false, CounterMappingRegion::CodeRegion));
 | 
						|
    }
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/// \brief Creates unreachable coverage regions for the functions that
 | 
						|
/// are not emitted.
 | 
						|
struct EmptyCoverageMappingBuilder : public CoverageMappingBuilder {
 | 
						|
  EmptyCoverageMappingBuilder(CoverageMappingModuleGen &CVM, SourceManager &SM,
 | 
						|
                              const LangOptions &LangOpts)
 | 
						|
      : CoverageMappingBuilder(CVM, SM, LangOpts) {}
 | 
						|
 | 
						|
  void VisitDecl(const Decl *D) {
 | 
						|
    if (!D->hasBody())
 | 
						|
      return;
 | 
						|
    auto Body = D->getBody();
 | 
						|
    mapSourceCodeRange(Body->getLocStart(), Body->getLocEnd(), Counter());
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Write the mapping data to the output stream
 | 
						|
  void write(llvm::raw_ostream &OS) {
 | 
						|
    emitSourceRegions();
 | 
						|
    SmallVector<unsigned, 16> FileIDMapping;
 | 
						|
    createFileIDMapping(FileIDMapping);
 | 
						|
 | 
						|
    CoverageMappingWriter Writer(
 | 
						|
        FileIDMapping, ArrayRef<CounterExpression>(), MappingRegions);
 | 
						|
    Writer.write(OS);
 | 
						|
  }
 | 
						|
};
 | 
						|
 | 
						|
/// \brief A StmtVisitor that creates coverage mapping regions which map
 | 
						|
/// from the source code locations to the PGO counters.
 | 
						|
struct CounterCoverageMappingBuilder
 | 
						|
    : public CoverageMappingBuilder,
 | 
						|
      public ConstStmtVisitor<CounterCoverageMappingBuilder> {
 | 
						|
  /// \brief The map of statements to count values.
 | 
						|
  llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
 | 
						|
 | 
						|
  Counter CurrentRegionCount;
 | 
						|
 | 
						|
  CounterExpressionBuilder Builder;
 | 
						|
 | 
						|
  /// \brief Return a counter that represents the
 | 
						|
  /// expression that subracts rhs from lhs.
 | 
						|
  Counter subtractCounters(Counter LHS, Counter RHS) {
 | 
						|
    return Builder.subtract(LHS, RHS);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Return a counter that represents the
 | 
						|
  /// the exression that adds lhs and rhs.
 | 
						|
  Counter addCounters(Counter LHS, Counter RHS) {
 | 
						|
    return Builder.add(LHS, RHS);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Return the region counter for the given statement.
 | 
						|
  /// This should only be called on statements that have a dedicated counter.
 | 
						|
  unsigned getRegionCounter(const Stmt *S) { return CounterMap[S]; }
 | 
						|
 | 
						|
  /// \brief Return the region count for the counter at the given index.
 | 
						|
  Counter getRegionCount(unsigned CounterId) {
 | 
						|
    return Counter::getCounter(CounterId);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Return the counter value of the current region.
 | 
						|
  Counter getCurrentRegionCount() { return CurrentRegionCount; }
 | 
						|
 | 
						|
  /// \brief Set the counter value for the current region.
 | 
						|
  /// This is used to keep track of changes to the most recent counter
 | 
						|
  /// from control flow and non-local exits.
 | 
						|
  void setCurrentRegionCount(Counter Count) {
 | 
						|
    CurrentRegionCount = Count;
 | 
						|
    CurrentUnreachableRegionInitiator = nullptr;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Indicate that the current region is never reached,
 | 
						|
  /// and thus should have a counter value of zero.
 | 
						|
  /// This is important so that subsequent regions can correctly track
 | 
						|
  /// their parent counts.
 | 
						|
  void setCurrentRegionUnreachable(const Stmt *Initiator) {
 | 
						|
    CurrentRegionCount = Counter::getZero();
 | 
						|
    CurrentUnreachableRegionInitiator = Initiator;
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief A counter for a particular region.
 | 
						|
  /// This is the primary interface through
 | 
						|
  /// which the coverage mapping builder manages counters and their values.
 | 
						|
  class RegionMapper {
 | 
						|
    CounterCoverageMappingBuilder &Mapping;
 | 
						|
    Counter Count;
 | 
						|
    Counter ParentCount;
 | 
						|
    Counter RegionCount;
 | 
						|
    Counter Adjust;
 | 
						|
 | 
						|
  public:
 | 
						|
    RegionMapper(CounterCoverageMappingBuilder *Mapper, const Stmt *S)
 | 
						|
        : Mapping(*Mapper),
 | 
						|
          Count(Mapper->getRegionCount(Mapper->getRegionCounter(S))),
 | 
						|
          ParentCount(Mapper->getCurrentRegionCount()) {}
 | 
						|
 | 
						|
    /// Get the value of the counter. In most cases this is the number of times
 | 
						|
    /// the region of the counter was entered, but for switch labels it's the
 | 
						|
    /// number of direct jumps to that label.
 | 
						|
    Counter getCount() const { return Count; }
 | 
						|
 | 
						|
    /// Get the value of the counter with adjustments applied. Adjustments occur
 | 
						|
    /// when control enters or leaves the region abnormally; i.e., if there is a
 | 
						|
    /// jump to a label within the region, or if the function can return from
 | 
						|
    /// within the region. The adjusted count, then, is the value of the counter
 | 
						|
    /// at the end of the region.
 | 
						|
    Counter getAdjustedCount() const {
 | 
						|
      return Mapping.addCounters(Count, Adjust);
 | 
						|
    }
 | 
						|
 | 
						|
    /// Get the value of the counter in this region's parent, i.e., the region
 | 
						|
    /// that was active when this region began. This is useful for deriving
 | 
						|
    /// counts in implicitly counted regions, like the false case of a condition
 | 
						|
    /// or the normal exits of a loop.
 | 
						|
    Counter getParentCount() const { return ParentCount; }
 | 
						|
 | 
						|
    /// Activate the counter by emitting an increment and starting to track
 | 
						|
    /// adjustments. If AddIncomingFallThrough is true, the current region count
 | 
						|
    /// will be added to the counter for the purposes of tracking the region.
 | 
						|
    void beginRegion(bool AddIncomingFallThrough = false) {
 | 
						|
      RegionCount = Count;
 | 
						|
      if (AddIncomingFallThrough)
 | 
						|
        RegionCount =
 | 
						|
            Mapping.addCounters(RegionCount, Mapping.getCurrentRegionCount());
 | 
						|
      Mapping.setCurrentRegionCount(RegionCount);
 | 
						|
    }
 | 
						|
 | 
						|
    /// For counters on boolean branches, begins tracking adjustments for the
 | 
						|
    /// uncounted path.
 | 
						|
    void beginElseRegion() {
 | 
						|
      RegionCount = Mapping.subtractCounters(ParentCount, Count);
 | 
						|
      Mapping.setCurrentRegionCount(RegionCount);
 | 
						|
    }
 | 
						|
 | 
						|
    /// Reset the current region count.
 | 
						|
    void setCurrentRegionCount(Counter CurrentCount) {
 | 
						|
      RegionCount = CurrentCount;
 | 
						|
      Mapping.setCurrentRegionCount(RegionCount);
 | 
						|
    }
 | 
						|
 | 
						|
    /// Adjust for non-local control flow after emitting a subexpression or
 | 
						|
    /// substatement. This must be called to account for constructs such as
 | 
						|
    /// gotos,
 | 
						|
    /// labels, and returns, so that we can ensure that our region's count is
 | 
						|
    /// correct in the code that follows.
 | 
						|
    void adjustForControlFlow() {
 | 
						|
      Adjust = Mapping.addCounters(
 | 
						|
          Adjust, Mapping.subtractCounters(Mapping.getCurrentRegionCount(),
 | 
						|
                                           RegionCount));
 | 
						|
      // Reset the region count in case this is called again later.
 | 
						|
      RegionCount = Mapping.getCurrentRegionCount();
 | 
						|
    }
 | 
						|
 | 
						|
    /// Commit all adjustments to the current region. If the region is a loop,
 | 
						|
    /// the LoopAdjust value should be the count of all the breaks and continues
 | 
						|
    /// from the loop, to compensate for those counts being deducted from the
 | 
						|
    /// adjustments for the body of the loop.
 | 
						|
    void applyAdjustmentsToRegion() {
 | 
						|
      Mapping.setCurrentRegionCount(Mapping.addCounters(ParentCount, Adjust));
 | 
						|
    }
 | 
						|
    void applyAdjustmentsToRegion(Counter LoopAdjust) {
 | 
						|
      Mapping.setCurrentRegionCount(Mapping.addCounters(
 | 
						|
          Mapping.addCounters(ParentCount, Adjust), LoopAdjust));
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  /// \brief Keep counts of breaks and continues inside loops.
 | 
						|
  struct BreakContinue {
 | 
						|
    Counter BreakCount;
 | 
						|
    Counter ContinueCount;
 | 
						|
  };
 | 
						|
  SmallVector<BreakContinue, 8> BreakContinueStack;
 | 
						|
 | 
						|
  CounterCoverageMappingBuilder(
 | 
						|
      CoverageMappingModuleGen &CVM,
 | 
						|
      llvm::DenseMap<const Stmt *, unsigned> &CounterMap,
 | 
						|
      unsigned NumRegionCounters, SourceManager &SM,
 | 
						|
      const LangOptions &LangOpts)
 | 
						|
      : CoverageMappingBuilder(CVM, SM, LangOpts), CounterMap(CounterMap),
 | 
						|
        Builder(NumRegionCounters) {}
 | 
						|
 | 
						|
  /// \brief Write the mapping data to the output stream
 | 
						|
  void write(llvm::raw_ostream &OS) {
 | 
						|
    emitSourceRegions();
 | 
						|
    llvm::SmallVector<unsigned, 8> VirtualFileMapping;
 | 
						|
    createFileIDMapping(VirtualFileMapping);
 | 
						|
    gatherSkippedRegions();
 | 
						|
 | 
						|
    CoverageMappingWriter Writer(
 | 
						|
        VirtualFileMapping, Builder.getExpressions(), MappingRegions);
 | 
						|
    Writer.write(OS);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Return the current source mapping state.
 | 
						|
  SourceMappingState getCurrentState() const {
 | 
						|
    return SourceMappingState(CurrentRegionCount, CurrentSourceGroup,
 | 
						|
                              CurrentUnreachableRegionInitiator);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Associate the source code range with the current region count.
 | 
						|
  void mapSourceCodeRange(SourceLocation LocStart, SourceLocation LocEnd,
 | 
						|
                          unsigned Flags = 0) {
 | 
						|
    CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocEnd,
 | 
						|
                                               CurrentRegionCount, Flags);
 | 
						|
  }
 | 
						|
 | 
						|
  void mapSourceCodeRange(SourceLocation LocStart) {
 | 
						|
    CoverageMappingBuilder::mapSourceCodeRange(LocStart, LocStart,
 | 
						|
                                               CurrentRegionCount);
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief Associate the source range of a token with the current region
 | 
						|
  /// count.
 | 
						|
  /// Ignore the source range for this token if it produces a distinct
 | 
						|
  /// mapping region with no other source ranges.
 | 
						|
  void mapToken(SourceLocation LocStart) {
 | 
						|
    CoverageMappingBuilder::mapSourceCodeRange(
 | 
						|
        LocStart, LocStart, CurrentRegionCount,
 | 
						|
        SourceMappingRegion::IgnoreIfNotExtended);
 | 
						|
  }
 | 
						|
 | 
						|
  void mapToken(const SourceMappingState &State, SourceLocation LocStart) {
 | 
						|
    CoverageMappingBuilder::mapSourceCodeRange(
 | 
						|
        State, LocStart, LocStart, SourceMappingRegion::IgnoreIfNotExtended);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitStmt(const Stmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    for (Stmt::const_child_range I = S->children(); I; ++I) {
 | 
						|
      if (*I)
 | 
						|
        this->Visit(*I);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /// \brief If the given statement is a compound statement,
 | 
						|
  /// map '}' with the same count as '{'.
 | 
						|
  void VisitSubStmtRBraceState(const Stmt *S) {
 | 
						|
    if (!isa<CompoundStmt>(S))
 | 
						|
      return Visit(S);
 | 
						|
    const auto *CS = cast<CompoundStmt>(S);
 | 
						|
    auto State = getCurrentState();
 | 
						|
    mapSourceCodeRange(CS->getLBracLoc());
 | 
						|
    for (Stmt::const_child_range I = S->children(); I; ++I) {
 | 
						|
      if (*I)
 | 
						|
        this->Visit(*I);
 | 
						|
    }
 | 
						|
    CoverageMappingBuilder::mapSourceCodeRange(State, CS->getRBracLoc(),
 | 
						|
                                               CS->getRBracLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitDecl(const Decl *D) {
 | 
						|
    if (!D->hasBody())
 | 
						|
      return;
 | 
						|
    // Counter tracks entry to the function body.
 | 
						|
    auto Body = D->getBody();
 | 
						|
    RegionMapper Cnt(this, Body);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    VisitSubStmtRBraceState(Body);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitDeclStmt(const DeclStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    for (Stmt::const_child_range I = static_cast<const Stmt *>(S)->children();
 | 
						|
         I; ++I) {
 | 
						|
      if (*I)
 | 
						|
        this->Visit(*I);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCompoundStmt(const CompoundStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLBracLoc());
 | 
						|
    for (Stmt::const_child_range I = S->children(); I; ++I) {
 | 
						|
      if (*I)
 | 
						|
        this->Visit(*I);
 | 
						|
    }
 | 
						|
    mapSourceCodeRange(S->getRBracLoc(), S->getRBracLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitReturnStmt(const ReturnStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    if (S->getRetValue())
 | 
						|
      Visit(S->getRetValue());
 | 
						|
    setCurrentRegionUnreachable(S);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitGotoStmt(const GotoStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    mapToken(S->getLabelLoc());
 | 
						|
    setCurrentRegionUnreachable(S);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitLabelStmt(const LabelStmt *S) {
 | 
						|
    // Counter tracks the block following the label.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    // Can't map the ':' token as its location isn't known.
 | 
						|
    Visit(S->getSubStmt());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitBreakStmt(const BreakStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
 | 
						|
    BreakContinueStack.back().BreakCount = addCounters(
 | 
						|
        BreakContinueStack.back().BreakCount, getCurrentRegionCount());
 | 
						|
    setCurrentRegionUnreachable(S);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitContinueStmt(const ContinueStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
 | 
						|
    BreakContinueStack.back().ContinueCount = addCounters(
 | 
						|
        BreakContinueStack.back().ContinueCount, getCurrentRegionCount());
 | 
						|
    setCurrentRegionUnreachable(S);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitWhileStmt(const WhileStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    // Counter tracks the body of the loop.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    BreakContinueStack.push_back(BreakContinue());
 | 
						|
    // Visit the body region first so the break/continue adjustments can be
 | 
						|
    // included when visiting the condition.
 | 
						|
    Cnt.beginRegion();
 | 
						|
    VisitSubStmtRBraceState(S->getBody());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
 | 
						|
    // ...then go back and propagate counts through the condition. The count
 | 
						|
    // at the start of the condition is the sum of the incoming edges,
 | 
						|
    // the backedge from the end of the loop body, and the edges from
 | 
						|
    // continue statements.
 | 
						|
    BreakContinue BC = BreakContinueStack.pop_back_val();
 | 
						|
    Cnt.setCurrentRegionCount(
 | 
						|
        addCounters(Cnt.getParentCount(),
 | 
						|
                    addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
 | 
						|
    beginSourceRegionGroup(S->getCond());
 | 
						|
    Visit(S->getCond());
 | 
						|
    endSourceRegionGroup();
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitDoStmt(const DoStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    // Counter tracks the body of the loop.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    BreakContinueStack.push_back(BreakContinue());
 | 
						|
    Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
 | 
						|
    VisitSubStmtRBraceState(S->getBody());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
 | 
						|
    BreakContinue BC = BreakContinueStack.pop_back_val();
 | 
						|
    // The count at the start of the condition is equal to the count at the
 | 
						|
    // end of the body. The adjusted count does not include either the
 | 
						|
    // fall-through count coming into the loop or the continue count, so add
 | 
						|
    // both of those separately. This is coincidentally the same equation as
 | 
						|
    // with while loops but for different reasons.
 | 
						|
    Cnt.setCurrentRegionCount(
 | 
						|
        addCounters(Cnt.getParentCount(),
 | 
						|
                    addCounters(Cnt.getAdjustedCount(), BC.ContinueCount)));
 | 
						|
    Visit(S->getCond());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitForStmt(const ForStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    if (S->getInit())
 | 
						|
      Visit(S->getInit());
 | 
						|
 | 
						|
    // Counter tracks the body of the loop.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    BreakContinueStack.push_back(BreakContinue());
 | 
						|
    // Visit the body region first. (This is basically the same as a while
 | 
						|
    // loop; see further comments in VisitWhileStmt.)
 | 
						|
    Cnt.beginRegion();
 | 
						|
    VisitSubStmtRBraceState(S->getBody());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
 | 
						|
    // The increment is essentially part of the body but it needs to include
 | 
						|
    // the count for all the continue statements.
 | 
						|
    if (S->getInc()) {
 | 
						|
      Cnt.setCurrentRegionCount(addCounters(
 | 
						|
          getCurrentRegionCount(), BreakContinueStack.back().ContinueCount));
 | 
						|
      beginSourceRegionGroup(S->getInc());
 | 
						|
      Visit(S->getInc());
 | 
						|
      endSourceRegionGroup();
 | 
						|
      Cnt.adjustForControlFlow();
 | 
						|
    }
 | 
						|
 | 
						|
    BreakContinue BC = BreakContinueStack.pop_back_val();
 | 
						|
 | 
						|
    // ...then go back and propagate counts through the condition.
 | 
						|
    if (S->getCond()) {
 | 
						|
      Cnt.setCurrentRegionCount(
 | 
						|
          addCounters(addCounters(Cnt.getParentCount(), Cnt.getAdjustedCount()),
 | 
						|
                      BC.ContinueCount));
 | 
						|
      beginSourceRegionGroup(S->getCond());
 | 
						|
      Visit(S->getCond());
 | 
						|
      endSourceRegionGroup();
 | 
						|
      Cnt.adjustForControlFlow();
 | 
						|
    }
 | 
						|
    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    Visit(S->getRangeStmt());
 | 
						|
    Visit(S->getBeginEndStmt());
 | 
						|
    // Counter tracks the body of the loop.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    BreakContinueStack.push_back(BreakContinue());
 | 
						|
    // Visit the body region first. (This is basically the same as a while
 | 
						|
    // loop; see further comments in VisitWhileStmt.)
 | 
						|
    Cnt.beginRegion();
 | 
						|
    VisitSubStmtRBraceState(S->getBody());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
    BreakContinue BC = BreakContinueStack.pop_back_val();
 | 
						|
    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    Visit(S->getElement());
 | 
						|
    // Counter tracks the body of the loop.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    BreakContinueStack.push_back(BreakContinue());
 | 
						|
    VisitSubStmtRBraceState(S->getBody());
 | 
						|
    BreakContinue BC = BreakContinueStack.pop_back_val();
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
    Cnt.applyAdjustmentsToRegion(addCounters(BC.BreakCount, BC.ContinueCount));
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitSwitchStmt(const SwitchStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    Visit(S->getCond());
 | 
						|
    BreakContinueStack.push_back(BreakContinue());
 | 
						|
    // Map the '}' for the body to have the same count as the regions after
 | 
						|
    // the switch.
 | 
						|
    SourceLocation RBracLoc;
 | 
						|
    if (const auto *CS = dyn_cast<CompoundStmt>(S->getBody())) {
 | 
						|
      mapSourceCodeRange(CS->getLBracLoc());
 | 
						|
      setCurrentRegionUnreachable(S);
 | 
						|
      for (Stmt::const_child_range I = CS->children(); I; ++I) {
 | 
						|
        if (*I)
 | 
						|
          this->Visit(*I);
 | 
						|
      }
 | 
						|
      RBracLoc = CS->getRBracLoc();
 | 
						|
    } else {
 | 
						|
      setCurrentRegionUnreachable(S);
 | 
						|
      Visit(S->getBody());
 | 
						|
    }
 | 
						|
    // If the switch is inside a loop, add the continue counts.
 | 
						|
    BreakContinue BC = BreakContinueStack.pop_back_val();
 | 
						|
    if (!BreakContinueStack.empty())
 | 
						|
      BreakContinueStack.back().ContinueCount = addCounters(
 | 
						|
          BreakContinueStack.back().ContinueCount, BC.ContinueCount);
 | 
						|
    // Counter tracks the exit block of the switch.
 | 
						|
    RegionMapper ExitCnt(this, S);
 | 
						|
    ExitCnt.beginRegion();
 | 
						|
    if (RBracLoc.isValid())
 | 
						|
      mapSourceCodeRange(RBracLoc);
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCaseStmt(const CaseStmt *S) {
 | 
						|
    // Counter for this particular case. This counts only jumps from the
 | 
						|
    // switch header and does not include fallthrough from the case before
 | 
						|
    // this one.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    mapToken(S->getColonLoc());
 | 
						|
    Visit(S->getSubStmt());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitDefaultStmt(const DefaultStmt *S) {
 | 
						|
    // Counter for this default case. This does not include fallthrough from
 | 
						|
    // the previous case.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    mapToken(S->getColonLoc());
 | 
						|
    Visit(S->getSubStmt());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitIfStmt(const IfStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    Visit(S->getCond());
 | 
						|
    mapToken(S->getElseLoc());
 | 
						|
 | 
						|
    // Counter tracks the "then" part of an if statement. The count for
 | 
						|
    // the "else" part, if it exists, will be calculated from this counter.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    VisitSubStmtRBraceState(S->getThen());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
 | 
						|
    if (S->getElse()) {
 | 
						|
      Cnt.beginElseRegion();
 | 
						|
      VisitSubStmtRBraceState(S->getElse());
 | 
						|
      Cnt.adjustForControlFlow();
 | 
						|
    }
 | 
						|
    Cnt.applyAdjustmentsToRegion();
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCXXTryStmt(const CXXTryStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    Visit(S->getTryBlock());
 | 
						|
    for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
 | 
						|
      Visit(S->getHandler(I));
 | 
						|
    // Counter tracks the continuation block of the try statement.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    Cnt.beginRegion();
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCXXCatchStmt(const CXXCatchStmt *S) {
 | 
						|
    mapSourceCodeRange(S->getLocStart());
 | 
						|
    // Counter tracks the catch statement's handler block.
 | 
						|
    RegionMapper Cnt(this, S);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    VisitSubStmtRBraceState(S->getHandlerBlock());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
 | 
						|
    Visit(E->getCond());
 | 
						|
    mapToken(E->getQuestionLoc());
 | 
						|
    auto State = getCurrentState();
 | 
						|
 | 
						|
    // Counter tracks the "true" part of a conditional operator. The
 | 
						|
    // count in the "false" part will be calculated from this counter.
 | 
						|
    RegionMapper Cnt(this, E);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    Visit(E->getTrueExpr());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
 | 
						|
    mapToken(State, E->getColonLoc());
 | 
						|
 | 
						|
    Cnt.beginElseRegion();
 | 
						|
    Visit(E->getFalseExpr());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
 | 
						|
    Cnt.applyAdjustmentsToRegion();
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitBinLAnd(const BinaryOperator *E) {
 | 
						|
    Visit(E->getLHS());
 | 
						|
    mapToken(E->getOperatorLoc());
 | 
						|
    // Counter tracks the right hand side of a logical and operator.
 | 
						|
    RegionMapper Cnt(this, E);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    Visit(E->getRHS());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
    Cnt.applyAdjustmentsToRegion();
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitBinLOr(const BinaryOperator *E) {
 | 
						|
    Visit(E->getLHS());
 | 
						|
    mapToken(E->getOperatorLoc());
 | 
						|
    // Counter tracks the right hand side of a logical or operator.
 | 
						|
    RegionMapper Cnt(this, E);
 | 
						|
    Cnt.beginRegion();
 | 
						|
    Visit(E->getRHS());
 | 
						|
    Cnt.adjustForControlFlow();
 | 
						|
    Cnt.applyAdjustmentsToRegion();
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitParenExpr(const ParenExpr *E) {
 | 
						|
    mapToken(E->getLParen());
 | 
						|
    Visit(E->getSubExpr());
 | 
						|
    mapToken(E->getRParen());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitBinaryOperator(const BinaryOperator *E) {
 | 
						|
    Visit(E->getLHS());
 | 
						|
    mapToken(E->getOperatorLoc());
 | 
						|
    Visit(E->getRHS());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitUnaryOperator(const UnaryOperator *E) {
 | 
						|
    bool Postfix = E->isPostfix();
 | 
						|
    if (!Postfix)
 | 
						|
      mapToken(E->getOperatorLoc());
 | 
						|
    Visit(E->getSubExpr());
 | 
						|
    if (Postfix)
 | 
						|
      mapToken(E->getOperatorLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitMemberExpr(const MemberExpr *E) {
 | 
						|
    Visit(E->getBase());
 | 
						|
    mapToken(E->getMemberLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCallExpr(const CallExpr *E) {
 | 
						|
    Visit(E->getCallee());
 | 
						|
    for (const auto &Arg : E->arguments())
 | 
						|
      Visit(Arg);
 | 
						|
    mapToken(E->getRParenLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
 | 
						|
    Visit(E->getLHS());
 | 
						|
    Visit(E->getRHS());
 | 
						|
    mapToken(E->getRBracketLoc());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCStyleCastExpr(const CStyleCastExpr *E) {
 | 
						|
    mapToken(E->getLParenLoc());
 | 
						|
    mapToken(E->getRParenLoc());
 | 
						|
    Visit(E->getSubExpr());
 | 
						|
  }
 | 
						|
 | 
						|
  // Map literals as tokens so that the macros like #define PI 3.14
 | 
						|
  // won't generate coverage mapping regions.
 | 
						|
 | 
						|
  void VisitIntegerLiteral(const IntegerLiteral *E) {
 | 
						|
    mapToken(E->getLocStart());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitFloatingLiteral(const FloatingLiteral *E) {
 | 
						|
    mapToken(E->getLocStart());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitCharacterLiteral(const CharacterLiteral *E) {
 | 
						|
    mapToken(E->getLocStart());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitStringLiteral(const StringLiteral *E) {
 | 
						|
    mapToken(E->getLocStart());
 | 
						|
  }
 | 
						|
 | 
						|
  void VisitImaginaryLiteral(const ImaginaryLiteral *E) {
 | 
						|
    mapToken(E->getLocStart());
 | 
						|
  }
 | 
						|
};
 | 
						|
}
 | 
						|
 | 
						|
static bool isMachO(const CodeGenModule &CGM) {
 | 
						|
  return CGM.getTarget().getTriple().isOSBinFormatMachO();
 | 
						|
}
 | 
						|
 | 
						|
static StringRef getCoverageSection(const CodeGenModule &CGM) {
 | 
						|
  return isMachO(CGM) ? "__DATA,__llvm_covmap" : "__llvm_covmap";
 | 
						|
}
 | 
						|
 | 
						|
void CoverageMappingModuleGen::addFunctionMappingRecord(
 | 
						|
    llvm::GlobalVariable *FunctionName, unsigned FunctionNameSize,
 | 
						|
    const std::string &CoverageMapping) {
 | 
						|
  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
 | 
						|
  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
 | 
						|
  auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
 | 
						|
  if (!FunctionRecordTy) {
 | 
						|
    llvm::Type *FunctionRecordTypes[] = {Int8PtrTy, Int32Ty, Int32Ty};
 | 
						|
    FunctionRecordTy =
 | 
						|
        llvm::StructType::get(Ctx, makeArrayRef(FunctionRecordTypes));
 | 
						|
  }
 | 
						|
 | 
						|
  llvm::Constant *FunctionRecordVals[] = {
 | 
						|
      llvm::ConstantExpr::getBitCast(FunctionName, Int8PtrTy),
 | 
						|
      llvm::ConstantInt::get(Int32Ty, FunctionNameSize),
 | 
						|
      llvm::ConstantInt::get(Int32Ty, CoverageMapping.size())};
 | 
						|
  FunctionRecords.push_back(llvm::ConstantStruct::get(
 | 
						|
      FunctionRecordTy, makeArrayRef(FunctionRecordVals)));
 | 
						|
  CoverageMappings += CoverageMapping;
 | 
						|
}
 | 
						|
 | 
						|
void CoverageMappingModuleGen::emit() {
 | 
						|
  if (FunctionRecords.empty())
 | 
						|
    return;
 | 
						|
  llvm::LLVMContext &Ctx = CGM.getLLVMContext();
 | 
						|
  auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
 | 
						|
 | 
						|
  // Create the filenames and merge them with coverage mappings
 | 
						|
  llvm::SmallVector<std::string, 16> FilenameStrs;
 | 
						|
  llvm::SmallVector<StringRef, 16> FilenameRefs;
 | 
						|
  FilenameStrs.resize(FileEntries.size());
 | 
						|
  FilenameRefs.resize(FileEntries.size());
 | 
						|
  for (const auto &Entry : FileEntries) {
 | 
						|
    llvm::SmallString<256> Path(Entry.first->getName());
 | 
						|
    llvm::sys::fs::make_absolute(Path);
 | 
						|
 | 
						|
    auto I = Entry.second;
 | 
						|
    FilenameStrs[I] = std::move(std::string(Path.begin(), Path.end()));
 | 
						|
    FilenameRefs[I] = FilenameStrs[I];
 | 
						|
  }
 | 
						|
 | 
						|
  std::string FilenamesAndCoverageMappings;
 | 
						|
  llvm::raw_string_ostream OS(FilenamesAndCoverageMappings);
 | 
						|
  CoverageFilenamesSectionWriter(FilenameRefs).write(OS);
 | 
						|
  OS << CoverageMappings;
 | 
						|
  size_t CoverageMappingSize = CoverageMappings.size();
 | 
						|
  size_t FilenamesSize = OS.str().size() - CoverageMappingSize;
 | 
						|
  // Append extra zeroes if necessary to ensure that the size of the filenames
 | 
						|
  // and coverage mappings is a multiple of 8.
 | 
						|
  if (size_t Rem = OS.str().size() % 8) {
 | 
						|
    CoverageMappingSize += 8 - Rem;
 | 
						|
    for (size_t I = 0, S = 8 - Rem; I < S; ++I)
 | 
						|
      OS << '\0';
 | 
						|
  }
 | 
						|
  auto *FilenamesAndMappingsVal =
 | 
						|
      llvm::ConstantDataArray::getString(Ctx, OS.str(), false);
 | 
						|
 | 
						|
  // Create the deferred function records array
 | 
						|
  auto RecordsTy =
 | 
						|
      llvm::ArrayType::get(FunctionRecordTy, FunctionRecords.size());
 | 
						|
  auto RecordsVal = llvm::ConstantArray::get(RecordsTy, FunctionRecords);
 | 
						|
 | 
						|
  // Create the coverage data record
 | 
						|
  llvm::Type *CovDataTypes[] = {Int32Ty,   Int32Ty,
 | 
						|
                                Int32Ty,   Int32Ty,
 | 
						|
                                RecordsTy, FilenamesAndMappingsVal->getType()};
 | 
						|
  auto CovDataTy = llvm::StructType::get(Ctx, makeArrayRef(CovDataTypes));
 | 
						|
  llvm::Constant *TUDataVals[] = {
 | 
						|
      llvm::ConstantInt::get(Int32Ty, FunctionRecords.size()),
 | 
						|
      llvm::ConstantInt::get(Int32Ty, FilenamesSize),
 | 
						|
      llvm::ConstantInt::get(Int32Ty, CoverageMappingSize),
 | 
						|
      llvm::ConstantInt::get(Int32Ty,
 | 
						|
                             /*Version=*/CoverageMappingVersion1),
 | 
						|
      RecordsVal, FilenamesAndMappingsVal};
 | 
						|
  auto CovDataVal =
 | 
						|
      llvm::ConstantStruct::get(CovDataTy, makeArrayRef(TUDataVals));
 | 
						|
  auto CovData = new llvm::GlobalVariable(CGM.getModule(), CovDataTy, true,
 | 
						|
                                          llvm::GlobalValue::InternalLinkage,
 | 
						|
                                          CovDataVal,
 | 
						|
                                          "__llvm_coverage_mapping");
 | 
						|
 | 
						|
  CovData->setSection(getCoverageSection(CGM));
 | 
						|
  CovData->setAlignment(8);
 | 
						|
 | 
						|
  // Make sure the data doesn't get deleted.
 | 
						|
  CGM.addUsedGlobal(CovData);
 | 
						|
}
 | 
						|
 | 
						|
unsigned CoverageMappingModuleGen::getFileID(const FileEntry *File) {
 | 
						|
  auto It = FileEntries.find(File);
 | 
						|
  if (It != FileEntries.end())
 | 
						|
    return It->second;
 | 
						|
  unsigned FileID = FileEntries.size();
 | 
						|
  FileEntries.insert(std::make_pair(File, FileID));
 | 
						|
  return FileID;
 | 
						|
}
 | 
						|
 | 
						|
void CoverageMappingGen::emitCounterMapping(const Decl *D,
 | 
						|
                                            llvm::raw_ostream &OS) {
 | 
						|
  assert(CounterMap);
 | 
						|
  CounterCoverageMappingBuilder Walker(CVM, *CounterMap, NumRegionCounters, SM,
 | 
						|
                                       LangOpts);
 | 
						|
  Walker.VisitDecl(D);
 | 
						|
  Walker.write(OS);
 | 
						|
}
 | 
						|
 | 
						|
void CoverageMappingGen::emitEmptyMapping(const Decl *D,
 | 
						|
                                          llvm::raw_ostream &OS) {
 | 
						|
  EmptyCoverageMappingBuilder Walker(CVM, SM, LangOpts);
 | 
						|
  Walker.VisitDecl(D);
 | 
						|
  Walker.write(OS);
 | 
						|
}
 |