//===- CodeCoverage.cpp - Coverage tool based on profiling instrumentation-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// The 'CodeCoverageTool' class implements a command line tool to analyze and
// report coverage information using the profiling instrumentation and code
// coverage mapping.
//
//===----------------------------------------------------------------------===//

#include "CoverageExporterJson.h"
#include "CoverageExporterLcov.h"
#include "CoverageFilters.h"
#include "CoverageReport.h"
#include "CoverageSummaryInfo.h"
#include "CoverageViewOptions.h"
#include "RenderingSupport.h"
#include "SourceCoverageView.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
#include "llvm/ProfileData/InstrProfReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/SpecialCaseList.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Support/VirtualFileSystem.h"

#include <functional>
#include <map>
#include <system_error>

using namespace llvm;
using namespace coverage;

void exportCoverageDataToJson(const coverage::CoverageMapping &CoverageMapping,
                              const CoverageViewOptions &Options,
                              raw_ostream &OS);

namespace {
/// The implementation of the coverage tool.
class CodeCoverageTool {
public:
  enum Command {
    /// The show command.
    Show,
    /// The report command.
    Report,
    /// The export command.
    Export
  };

  int run(Command Cmd, int argc, const char **argv);

private:
  /// Print the error message to the error output stream.
  void error(const Twine &Message, StringRef Whence = "");

  /// Print the warning message to the error output stream.
  void warning(const Twine &Message, StringRef Whence = "");

  /// Convert \p Path into an absolute path and append it to the list
  /// of collected paths.
  void addCollectedPath(const std::string &Path);

  /// If \p Path is a regular file, collect the path. If it's a
  /// directory, recursively collect all of the paths within the directory.
  void collectPaths(const std::string &Path);

  /// Check if the two given files are the same file.
  bool isEquivalentFile(StringRef FilePath1, StringRef FilePath2);

  /// Retrieve a file status with a cache.
  Optional<sys::fs::file_status> getFileStatus(StringRef FilePath);

  /// Return a memory buffer for the given source file.
  ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile);

  /// Create source views for the expansions of the view.
  void attachExpansionSubViews(SourceCoverageView &View,
                               ArrayRef<ExpansionRecord> Expansions,
                               const CoverageMapping &Coverage);

  /// Create source views for the branches of the view.
  void attachBranchSubViews(SourceCoverageView &View, StringRef SourceName,
                            ArrayRef<CountedRegion> Branches,
                            const MemoryBuffer &File,
                            CoverageData &CoverageInfo);

  /// Create the source view of a particular function.
  std::unique_ptr<SourceCoverageView>
  createFunctionView(const FunctionRecord &Function,
                     const CoverageMapping &Coverage);

  /// Create the main source view of a particular source file.
  std::unique_ptr<SourceCoverageView>
  createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage);

  /// Load the coverage mapping data. Return nullptr if an error occurred.
  std::unique_ptr<CoverageMapping> load();

  /// Create a mapping from files in the Coverage data to local copies
  /// (path-equivalence).
  void remapPathNames(const CoverageMapping &Coverage);

  /// Remove input source files which aren't mapped by \p Coverage.
  void removeUnmappedInputs(const CoverageMapping &Coverage);

  /// If a demangler is available, demangle all symbol names.
  void demangleSymbols(const CoverageMapping &Coverage);

  /// Write out a source file view to the filesystem.
  void writeSourceFileView(StringRef SourceFile, CoverageMapping *Coverage,
                           CoveragePrinter *Printer, bool ShowFilenames);

  typedef llvm::function_ref<int(int, const char **)> CommandLineParserType;

  int doShow(int argc, const char **argv,
             CommandLineParserType commandLineParser);

  int doReport(int argc, const char **argv,
               CommandLineParserType commandLineParser);

  int doExport(int argc, const char **argv,
               CommandLineParserType commandLineParser);

  std::vector<StringRef> ObjectFilenames;
  CoverageViewOptions ViewOpts;
  CoverageFiltersMatchAll Filters;
  CoverageFilters IgnoreFilenameFilters;

  /// True if InputSourceFiles are provided.
  bool HadSourceFiles = false;

  /// The path to the indexed profile.
  std::string PGOFilename;

  /// A list of input source files.
  std::vector<std::string> SourceFiles;

  /// In -path-equivalence mode, this maps the absolute paths from the coverage
  /// mapping data to the input source files.
  StringMap<std::string> RemappedFilenames;

  /// The coverage data path to be remapped from, and the source path to be
  /// remapped to, when using -path-equivalence.
  Optional<std::pair<std::string, std::string>> PathRemapping;

  /// File status cache used when finding the same file.
  StringMap<Optional<sys::fs::file_status>> FileStatusCache;

  /// The architecture the coverage mapping data targets.
  std::vector<StringRef> CoverageArches;

  /// A cache for demangled symbols.
  DemangleCache DC;

  /// A lock which guards printing to stderr.
  std::mutex ErrsLock;

  /// A container for input source file buffers.
  std::mutex LoadedSourceFilesLock;
  std::vector<std::pair<std::string, std::unique_ptr<MemoryBuffer>>>
      LoadedSourceFiles;

  /// Allowlist from -name-allowlist to be used for filtering.
  std::unique_ptr<SpecialCaseList> NameAllowlist;
};
}

static std::string getErrorString(const Twine &Message, StringRef Whence,
                                  bool Warning) {
  std::string Str = (Warning ? "warning" : "error");
  Str += ": ";
  if (!Whence.empty())
    Str += Whence.str() + ": ";
  Str += Message.str() + "\n";
  return Str;
}

void CodeCoverageTool::error(const Twine &Message, StringRef Whence) {
  std::unique_lock<std::mutex> Guard{ErrsLock};
  ViewOpts.colored_ostream(errs(), raw_ostream::RED)
      << getErrorString(Message, Whence, false);
}

void CodeCoverageTool::warning(const Twine &Message, StringRef Whence) {
  std::unique_lock<std::mutex> Guard{ErrsLock};
  ViewOpts.colored_ostream(errs(), raw_ostream::RED)
      << getErrorString(Message, Whence, true);
}

void CodeCoverageTool::addCollectedPath(const std::string &Path) {
  SmallString<128> EffectivePath(Path);
  if (std::error_code EC = sys::fs::make_absolute(EffectivePath)) {
    error(EC.message(), Path);
    return;
  }
  sys::path::remove_dots(EffectivePath, /*remove_dot_dot=*/true);
  if (!IgnoreFilenameFilters.matchesFilename(EffectivePath))
    SourceFiles.emplace_back(EffectivePath.str());
  HadSourceFiles = !SourceFiles.empty();
}

void CodeCoverageTool::collectPaths(const std::string &Path) {
  llvm::sys::fs::file_status Status;
  llvm::sys::fs::status(Path, Status);
  if (!llvm::sys::fs::exists(Status)) {
    if (PathRemapping)
      addCollectedPath(Path);
    else
      warning("Source file doesn't exist, proceeded by ignoring it.", Path);
    return;
  }

  if (llvm::sys::fs::is_regular_file(Status)) {
    addCollectedPath(Path);
    return;
  }

  if (llvm::sys::fs::is_directory(Status)) {
    std::error_code EC;
    for (llvm::sys::fs::recursive_directory_iterator F(Path, EC), E;
         F != E; F.increment(EC)) {

      auto Status = F->status();
      if (!Status) {
        warning(Status.getError().message(), F->path());
        continue;
      }

      if (Status->type() == llvm::sys::fs::file_type::regular_file)
        addCollectedPath(F->path());
    }
  }
}

Optional<sys::fs::file_status>
CodeCoverageTool::getFileStatus(StringRef FilePath) {
  auto It = FileStatusCache.try_emplace(FilePath);
  auto &CachedStatus = It.first->getValue();
  if (!It.second)
    return CachedStatus;

  sys::fs::file_status Status;
  if (!sys::fs::status(FilePath, Status))
    CachedStatus = Status;
  return CachedStatus;
}

bool CodeCoverageTool::isEquivalentFile(StringRef FilePath1,
                                        StringRef FilePath2) {
  auto Status1 = getFileStatus(FilePath1);
  auto Status2 = getFileStatus(FilePath2);
  return Status1.hasValue() && Status2.hasValue() &&
         sys::fs::equivalent(Status1.getValue(), Status2.getValue());
}

ErrorOr<const MemoryBuffer &>
CodeCoverageTool::getSourceFile(StringRef SourceFile) {
  // If we've remapped filenames, look up the real location for this file.
  std::unique_lock<std::mutex> Guard{LoadedSourceFilesLock};
  if (!RemappedFilenames.empty()) {
    auto Loc = RemappedFilenames.find(SourceFile);
    if (Loc != RemappedFilenames.end())
      SourceFile = Loc->second;
  }
  for (const auto &Files : LoadedSourceFiles)
    if (isEquivalentFile(SourceFile, Files.first))
      return *Files.second;
  auto Buffer = MemoryBuffer::getFile(SourceFile);
  if (auto EC = Buffer.getError()) {
    error(EC.message(), SourceFile);
    return EC;
  }
  LoadedSourceFiles.emplace_back(std::string(SourceFile),
                                 std::move(Buffer.get()));
  return *LoadedSourceFiles.back().second;
}

void CodeCoverageTool::attachExpansionSubViews(
    SourceCoverageView &View, ArrayRef<ExpansionRecord> Expansions,
    const CoverageMapping &Coverage) {
  if (!ViewOpts.ShowExpandedRegions)
    return;
  for (const auto &Expansion : Expansions) {
    auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
    if (ExpansionCoverage.empty())
      continue;
    auto SourceBuffer = getSourceFile(ExpansionCoverage.getFilename());
    if (!SourceBuffer)
      continue;

    auto SubViewBranches = ExpansionCoverage.getBranches();
    auto SubViewExpansions = ExpansionCoverage.getExpansions();
    auto SubView =
        SourceCoverageView::create(Expansion.Function.Name, SourceBuffer.get(),
                                   ViewOpts, std::move(ExpansionCoverage));
    attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
    attachBranchSubViews(*SubView, Expansion.Function.Name, SubViewBranches,
                         SourceBuffer.get(), ExpansionCoverage);
    View.addExpansion(Expansion.Region, std::move(SubView));
  }
}

void CodeCoverageTool::attachBranchSubViews(SourceCoverageView &View,
                                            StringRef SourceName,
                                            ArrayRef<CountedRegion> Branches,
                                            const MemoryBuffer &File,
                                            CoverageData &CoverageInfo) {
  if (!ViewOpts.ShowBranchCounts && !ViewOpts.ShowBranchPercents)
    return;

  const auto *NextBranch = Branches.begin();
  const auto *EndBranch = Branches.end();

  // Group branches that have the same line number into the same subview.
  while (NextBranch != EndBranch) {
    std::vector<CountedRegion> ViewBranches;
    unsigned CurrentLine = NextBranch->LineStart;

    while (NextBranch != EndBranch && CurrentLine == NextBranch->LineStart)
      ViewBranches.push_back(*NextBranch++);

    if (!ViewBranches.empty()) {
      auto SubView = SourceCoverageView::create(SourceName, File, ViewOpts,
                                                std::move(CoverageInfo));
      View.addBranch(CurrentLine, ViewBranches, std::move(SubView));
    }
  }
}

std::unique_ptr<SourceCoverageView>
CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
                                     const CoverageMapping &Coverage) {
  auto FunctionCoverage = Coverage.getCoverageForFunction(Function);
  if (FunctionCoverage.empty())
    return nullptr;
  auto SourceBuffer = getSourceFile(FunctionCoverage.getFilename());
  if (!SourceBuffer)
    return nullptr;

  auto Branches = FunctionCoverage.getBranches();
  auto Expansions = FunctionCoverage.getExpansions();
  auto View = SourceCoverageView::create(DC.demangle(Function.Name),
                                         SourceBuffer.get(), ViewOpts,
                                         std::move(FunctionCoverage));
  attachExpansionSubViews(*View, Expansions, Coverage);
  attachBranchSubViews(*View, DC.demangle(Function.Name), Branches,
                       SourceBuffer.get(), FunctionCoverage);

  return View;
}

std::unique_ptr<SourceCoverageView>
CodeCoverageTool::createSourceFileView(StringRef SourceFile,
                                       const CoverageMapping &Coverage) {
  auto SourceBuffer = getSourceFile(SourceFile);
  if (!SourceBuffer)
    return nullptr;
  auto FileCoverage = Coverage.getCoverageForFile(SourceFile);
  if (FileCoverage.empty())
    return nullptr;

  auto Branches = FileCoverage.getBranches();
  auto Expansions = FileCoverage.getExpansions();
  auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
                                         ViewOpts, std::move(FileCoverage));
  attachExpansionSubViews(*View, Expansions, Coverage);
  attachBranchSubViews(*View, SourceFile, Branches, SourceBuffer.get(),
                       FileCoverage);
  if (!ViewOpts.ShowFunctionInstantiations)
    return View;

  for (const auto &Group : Coverage.getInstantiationGroups(SourceFile)) {
    // Skip functions which have a single instantiation.
    if (Group.size() < 2)
      continue;

    for (const FunctionRecord *Function : Group.getInstantiations()) {
      std::unique_ptr<SourceCoverageView> SubView{nullptr};

      StringRef Funcname = DC.demangle(Function->Name);

      if (Function->ExecutionCount > 0) {
        auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
        auto SubViewExpansions = SubViewCoverage.getExpansions();
        auto SubViewBranches = SubViewCoverage.getBranches();
        SubView = SourceCoverageView::create(
            Funcname, SourceBuffer.get(), ViewOpts, std::move(SubViewCoverage));
        attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
        attachBranchSubViews(*SubView, SourceFile, SubViewBranches,
                             SourceBuffer.get(), SubViewCoverage);
      }

      unsigned FileID = Function->CountedRegions.front().FileID;
      unsigned Line = 0;
      for (const auto &CR : Function->CountedRegions)
        if (CR.FileID == FileID)
          Line = std::max(CR.LineEnd, Line);
      View->addInstantiation(Funcname, Line, std::move(SubView));
    }
  }
  return View;
}

static bool modifiedTimeGT(StringRef LHS, StringRef RHS) {
  sys::fs::file_status Status;
  if (sys::fs::status(LHS, Status))
    return false;
  auto LHSTime = Status.getLastModificationTime();
  if (sys::fs::status(RHS, Status))
    return false;
  auto RHSTime = Status.getLastModificationTime();
  return LHSTime > RHSTime;
}

std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
  for (StringRef ObjectFilename : ObjectFilenames)
    if (modifiedTimeGT(ObjectFilename, PGOFilename))
      warning("profile data may be out of date - object is newer",
              ObjectFilename);
  auto CoverageOrErr =
      CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches,
                            ViewOpts.CompilationDirectory);
  if (Error E = CoverageOrErr.takeError()) {
    error("Failed to load coverage: " + toString(std::move(E)),
          join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "));
    return nullptr;
  }
  auto Coverage = std::move(CoverageOrErr.get());
  unsigned Mismatched = Coverage->getMismatchedCount();
  if (Mismatched) {
    warning(Twine(Mismatched) + " functions have mismatched data");

    if (ViewOpts.Debug) {
      for (const auto &HashMismatch : Coverage->getHashMismatches())
        errs() << "hash-mismatch: "
               << "No profile record found for '" << HashMismatch.first << "'"
               << " with hash = 0x" << Twine::utohexstr(HashMismatch.second)
               << '\n';
    }
  }

  remapPathNames(*Coverage);

  if (!SourceFiles.empty())
    removeUnmappedInputs(*Coverage);

  demangleSymbols(*Coverage);

  return Coverage;
}

void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
  if (!PathRemapping)
    return;

  // Convert remapping paths to native paths with trailing seperators.
  auto nativeWithTrailing = [](StringRef Path) -> std::string {
    if (Path.empty())
      return "";
    SmallString<128> NativePath;
    sys::path::native(Path, NativePath);
    sys::path::remove_dots(NativePath, true);
    if (!NativePath.empty() && !sys::path::is_separator(NativePath.back()))
      NativePath += sys::path::get_separator();
    return NativePath.c_str();
  };
  std::string RemapFrom = nativeWithTrailing(PathRemapping->first);
  std::string RemapTo = nativeWithTrailing(PathRemapping->second);

  // Create a mapping from coverage data file paths to local paths.
  for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
    SmallString<128> NativeFilename;
    sys::path::native(Filename, NativeFilename);
    sys::path::remove_dots(NativeFilename, true);
    if (NativeFilename.startswith(RemapFrom)) {
      RemappedFilenames[Filename] =
          RemapTo + NativeFilename.substr(RemapFrom.size()).str();
    }
  }

  // Convert input files from local paths to coverage data file paths.
  StringMap<std::string> InvRemappedFilenames;
  for (const auto &RemappedFilename : RemappedFilenames)
    InvRemappedFilenames[RemappedFilename.getValue()] =
        std::string(RemappedFilename.getKey());

  for (std::string &Filename : SourceFiles) {
    SmallString<128> NativeFilename;
    sys::path::native(Filename, NativeFilename);
    auto CovFileName = InvRemappedFilenames.find(NativeFilename);
    if (CovFileName != InvRemappedFilenames.end())
      Filename = CovFileName->second;
  }
}

void CodeCoverageTool::removeUnmappedInputs(const CoverageMapping &Coverage) {
  std::vector<StringRef> CoveredFiles = Coverage.getUniqueSourceFiles();

  // The user may have specified source files which aren't in the coverage
  // mapping. Filter these files away.
  llvm::erase_if(SourceFiles, [&](const std::string &SF) {
    return !std::binary_search(CoveredFiles.begin(), CoveredFiles.end(), SF);
  });
}

void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {
  if (!ViewOpts.hasDemangler())
    return;

  // Pass function names to the demangler in a temporary file.
  int InputFD;
  SmallString<256> InputPath;
  std::error_code EC =
      sys::fs::createTemporaryFile("demangle-in", "list", InputFD, InputPath);
  if (EC) {
    error(InputPath, EC.message());
    return;
  }
  ToolOutputFile InputTOF{InputPath, InputFD};

  unsigned NumSymbols = 0;
  for (const auto &Function : Coverage.getCoveredFunctions()) {
    InputTOF.os() << Function.Name << '\n';
    ++NumSymbols;
  }
  InputTOF.os().close();

  // Use another temporary file to store the demangler's output.
  int OutputFD;
  SmallString<256> OutputPath;
  EC = sys::fs::createTemporaryFile("demangle-out", "list", OutputFD,
                                    OutputPath);
  if (EC) {
    error(OutputPath, EC.message());
    return;
  }
  ToolOutputFile OutputTOF{OutputPath, OutputFD};
  OutputTOF.os().close();

  // Invoke the demangler.
  std::vector<StringRef> ArgsV;
  for (StringRef Arg : ViewOpts.DemanglerOpts)
    ArgsV.push_back(Arg);
  Optional<StringRef> Redirects[] = {InputPath.str(), OutputPath.str(), {""}};
  std::string ErrMsg;
  int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV,
                               /*env=*/None, Redirects, /*secondsToWait=*/0,
                               /*memoryLimit=*/0, &ErrMsg);
  if (RC) {
    error(ErrMsg, ViewOpts.DemanglerOpts[0]);
    return;
  }

  // Parse the demangler's output.
  auto BufOrError = MemoryBuffer::getFile(OutputPath);
  if (!BufOrError) {
    error(OutputPath, BufOrError.getError().message());
    return;
  }

  std::unique_ptr<MemoryBuffer> DemanglerBuf = std::move(*BufOrError);

  SmallVector<StringRef, 8> Symbols;
  StringRef DemanglerData = DemanglerBuf->getBuffer();
  DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols,
                      /*KeepEmpty=*/false);
  if (Symbols.size() != NumSymbols) {
    error("Demangler did not provide expected number of symbols");
    return;
  }

  // Cache the demangled names.
  unsigned I = 0;
  for (const auto &Function : Coverage.getCoveredFunctions())
    // On Windows, lines in the demangler's output file end with "\r\n".
    // Splitting by '\n' keeps '\r's, so cut them now.
    DC.DemangledNames[Function.Name] = std::string(Symbols[I++].rtrim());
}

void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
                                           CoverageMapping *Coverage,
                                           CoveragePrinter *Printer,
                                           bool ShowFilenames) {
  auto View = createSourceFileView(SourceFile, *Coverage);
  if (!View) {
    warning("The file '" + SourceFile + "' isn't covered.");
    return;
  }

  auto OSOrErr = Printer->createViewFile(SourceFile, /*InToplevel=*/false);
  if (Error E = OSOrErr.takeError()) {
    error("Could not create view file!", toString(std::move(E)));
    return;
  }
  auto OS = std::move(OSOrErr.get());

  View->print(*OS.get(), /*Wholefile=*/true,
              /*ShowSourceName=*/ShowFilenames,
              /*ShowTitle=*/ViewOpts.hasOutputDirectory());
  Printer->closeViewFile(std::move(OS));
}

int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
  cl::opt<std::string> CovFilename(
      cl::Positional, cl::desc("Covered executable or object file."));

  cl::list<std::string> CovFilenames(
      "object", cl::desc("Coverage executable or object file"), cl::ZeroOrMore);

  cl::opt<bool> DebugDumpCollectedObjects(
      "dump-collected-objects", cl::Optional, cl::Hidden,
      cl::desc("Show the collected coverage object files"));

  cl::list<std::string> InputSourceFiles(
      cl::Positional, cl::desc("<Source files>"), cl::ZeroOrMore);

  cl::opt<bool> DebugDumpCollectedPaths(
      "dump-collected-paths", cl::Optional, cl::Hidden,
      cl::desc("Show the collected paths to source files"));

  cl::opt<std::string, true> PGOFilename(
      "instr-profile", cl::Required, cl::location(this->PGOFilename),
      cl::desc(
          "File with the profile data obtained after an instrumented run"));

  cl::list<std::string> Arches(
      "arch", cl::desc("architectures of the coverage mapping binaries"));

  cl::opt<bool> DebugDump("dump", cl::Optional,
                          cl::desc("Show internal debug dump"));

  cl::opt<CoverageViewOptions::OutputFormat> Format(
      "format", cl::desc("Output format for line-based coverage reports"),
      cl::values(clEnumValN(CoverageViewOptions::OutputFormat::Text, "text",
                            "Text output"),
                 clEnumValN(CoverageViewOptions::OutputFormat::HTML, "html",
                            "HTML output"),
                 clEnumValN(CoverageViewOptions::OutputFormat::Lcov, "lcov",
                            "lcov tracefile output")),
      cl::init(CoverageViewOptions::OutputFormat::Text));

  cl::opt<std::string> PathRemap(
      "path-equivalence", cl::Optional,
      cl::desc("<from>,<to> Map coverage data paths to local source file "
               "paths"));

  cl::OptionCategory FilteringCategory("Function filtering options");

  cl::list<std::string> NameFilters(
      "name", cl::Optional,
      cl::desc("Show code coverage only for functions with the given name"),
      cl::ZeroOrMore, cl::cat(FilteringCategory));

  cl::list<std::string> NameFilterFiles(
      "name-allowlist", cl::Optional,
      cl::desc("Show code coverage only for functions listed in the given "
               "file"),
      cl::ZeroOrMore, cl::cat(FilteringCategory));

  // Allow for accepting previous option name.
  cl::list<std::string> NameFilterFilesDeprecated(
      "name-whitelist", cl::Optional, cl::Hidden,
      cl::desc("Show code coverage only for functions listed in the given "
               "file. Deprecated, use -name-allowlist instead"),
      cl::ZeroOrMore, cl::cat(FilteringCategory));

  cl::list<std::string> NameRegexFilters(
      "name-regex", cl::Optional,
      cl::desc("Show code coverage only for functions that match the given "
               "regular expression"),
      cl::ZeroOrMore, cl::cat(FilteringCategory));

  cl::list<std::string> IgnoreFilenameRegexFilters(
      "ignore-filename-regex", cl::Optional,
      cl::desc("Skip source code files with file paths that match the given "
               "regular expression"),
      cl::ZeroOrMore, cl::cat(FilteringCategory));

  cl::opt<double> RegionCoverageLtFilter(
      "region-coverage-lt", cl::Optional,
      cl::desc("Show code coverage only for functions with region coverage "
               "less than the given threshold"),
      cl::cat(FilteringCategory));

  cl::opt<double> RegionCoverageGtFilter(
      "region-coverage-gt", cl::Optional,
      cl::desc("Show code coverage only for functions with region coverage "
               "greater than the given threshold"),
      cl::cat(FilteringCategory));

  cl::opt<double> LineCoverageLtFilter(
      "line-coverage-lt", cl::Optional,
      cl::desc("Show code coverage only for functions with line coverage less "
               "than the given threshold"),
      cl::cat(FilteringCategory));

  cl::opt<double> LineCoverageGtFilter(
      "line-coverage-gt", cl::Optional,
      cl::desc("Show code coverage only for functions with line coverage "
               "greater than the given threshold"),
      cl::cat(FilteringCategory));

  cl::opt<cl::boolOrDefault> UseColor(
      "use-color", cl::desc("Emit colored output (default=autodetect)"),
      cl::init(cl::BOU_UNSET));

  cl::list<std::string> DemanglerOpts(
      "Xdemangler", cl::desc("<demangler-path>|<demangler-option>"));

  cl::opt<bool> RegionSummary(
      "show-region-summary", cl::Optional,
      cl::desc("Show region statistics in summary table"),
      cl::init(true));

  cl::opt<bool> BranchSummary(
      "show-branch-summary", cl::Optional,
      cl::desc("Show branch condition statistics in summary table"),
      cl::init(true));

  cl::opt<bool> InstantiationSummary(
      "show-instantiation-summary", cl::Optional,
      cl::desc("Show instantiation statistics in summary table"));

  cl::opt<bool> SummaryOnly(
      "summary-only", cl::Optional,
      cl::desc("Export only summary information for each source file"));

  cl::opt<unsigned> NumThreads(
      "num-threads", cl::init(0),
      cl::desc("Number of merge threads to use (default: autodetect)"));
  cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
                        cl::aliasopt(NumThreads));

  cl::opt<std::string> CompilationDirectory(
      "compilation-dir", cl::init(""),
      cl::desc("Directory used as a base for relative coverage mapping paths"));

  auto commandLineParser = [&, this](int argc, const char **argv) -> int {
    cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
    ViewOpts.Debug = DebugDump;

    if (!CovFilename.empty())
      ObjectFilenames.emplace_back(CovFilename);
    for (const std::string &Filename : CovFilenames)
      ObjectFilenames.emplace_back(Filename);
    if (ObjectFilenames.empty()) {
      errs() << "No filenames specified!\n";
      ::exit(1);
    }

    if (DebugDumpCollectedObjects) {
      for (StringRef OF : ObjectFilenames)
        outs() << OF << '\n';
      ::exit(0);
    }

    ViewOpts.Format = Format;
    switch (ViewOpts.Format) {
    case CoverageViewOptions::OutputFormat::Text:
      ViewOpts.Colors = UseColor == cl::BOU_UNSET
                            ? sys::Process::StandardOutHasColors()
                            : UseColor == cl::BOU_TRUE;
      break;
    case CoverageViewOptions::OutputFormat::HTML:
      if (UseColor == cl::BOU_FALSE)
        errs() << "Color output cannot be disabled when generating html.\n";
      ViewOpts.Colors = true;
      break;
    case CoverageViewOptions::OutputFormat::Lcov:
      if (UseColor == cl::BOU_TRUE)
        errs() << "Color output cannot be enabled when generating lcov.\n";
      ViewOpts.Colors = false;
      break;
    }

    // If path-equivalence was given and is a comma seperated pair then set
    // PathRemapping.
    if (!PathRemap.empty()) {
      auto EquivPair = StringRef(PathRemap).split(',');
      if (EquivPair.first.empty() || EquivPair.second.empty()) {
        error("invalid argument '" + PathRemap +
                  "', must be in format 'from,to'",
              "-path-equivalence");
        return 1;
      }

      PathRemapping = {std::string(EquivPair.first),
                       std::string(EquivPair.second)};
    }

    // If a demangler is supplied, check if it exists and register it.
    if (!DemanglerOpts.empty()) {
      auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]);
      if (!DemanglerPathOrErr) {
        error("Could not find the demangler!",
              DemanglerPathOrErr.getError().message());
        return 1;
      }
      DemanglerOpts[0] = *DemanglerPathOrErr;
      ViewOpts.DemanglerOpts.swap(DemanglerOpts);
    }

    // Read in -name-allowlist files.
    if (!NameFilterFiles.empty() || !NameFilterFilesDeprecated.empty()) {
      std::string SpecialCaseListErr;
      if (!NameFilterFiles.empty())
        NameAllowlist = SpecialCaseList::create(
            NameFilterFiles, *vfs::getRealFileSystem(), SpecialCaseListErr);
      if (!NameFilterFilesDeprecated.empty())
        NameAllowlist = SpecialCaseList::create(NameFilterFilesDeprecated,
                                                *vfs::getRealFileSystem(),
                                                SpecialCaseListErr);

      if (!NameAllowlist)
        error(SpecialCaseListErr);
    }

    // Create the function filters
    if (!NameFilters.empty() || NameAllowlist || !NameRegexFilters.empty()) {
      auto NameFilterer = std::make_unique<CoverageFilters>();
      for (const auto &Name : NameFilters)
        NameFilterer->push_back(std::make_unique<NameCoverageFilter>(Name));
      if (NameAllowlist) {
        if (!NameFilterFiles.empty())
          NameFilterer->push_back(
              std::make_unique<NameAllowlistCoverageFilter>(*NameAllowlist));
        if (!NameFilterFilesDeprecated.empty())
          NameFilterer->push_back(
              std::make_unique<NameWhitelistCoverageFilter>(*NameAllowlist));
      }
      for (const auto &Regex : NameRegexFilters)
        NameFilterer->push_back(
            std::make_unique<NameRegexCoverageFilter>(Regex));
      Filters.push_back(std::move(NameFilterer));
    }

    if (RegionCoverageLtFilter.getNumOccurrences() ||
        RegionCoverageGtFilter.getNumOccurrences() ||
        LineCoverageLtFilter.getNumOccurrences() ||
        LineCoverageGtFilter.getNumOccurrences()) {
      auto StatFilterer = std::make_unique<CoverageFilters>();
      if (RegionCoverageLtFilter.getNumOccurrences())
        StatFilterer->push_back(std::make_unique<RegionCoverageFilter>(
            RegionCoverageFilter::LessThan, RegionCoverageLtFilter));
      if (RegionCoverageGtFilter.getNumOccurrences())
        StatFilterer->push_back(std::make_unique<RegionCoverageFilter>(
            RegionCoverageFilter::GreaterThan, RegionCoverageGtFilter));
      if (LineCoverageLtFilter.getNumOccurrences())
        StatFilterer->push_back(std::make_unique<LineCoverageFilter>(
            LineCoverageFilter::LessThan, LineCoverageLtFilter));
      if (LineCoverageGtFilter.getNumOccurrences())
        StatFilterer->push_back(std::make_unique<LineCoverageFilter>(
            RegionCoverageFilter::GreaterThan, LineCoverageGtFilter));
      Filters.push_back(std::move(StatFilterer));
    }

    // Create the ignore filename filters.
    for (const auto &RE : IgnoreFilenameRegexFilters)
      IgnoreFilenameFilters.push_back(
          std::make_unique<NameRegexCoverageFilter>(RE));

    if (!Arches.empty()) {
      for (const std::string &Arch : Arches) {
        if (Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) {
          error("Unknown architecture: " + Arch);
          return 1;
        }
        CoverageArches.emplace_back(Arch);
      }
      if (CoverageArches.size() != ObjectFilenames.size()) {
        error("Number of architectures doesn't match the number of objects");
        return 1;
      }
    }

    // IgnoreFilenameFilters are applied even when InputSourceFiles specified.
    for (const std::string &File : InputSourceFiles)
      collectPaths(File);

    if (DebugDumpCollectedPaths) {
      for (const std::string &SF : SourceFiles)
        outs() << SF << '\n';
      ::exit(0);
    }

    ViewOpts.ShowBranchSummary = BranchSummary;
    ViewOpts.ShowRegionSummary = RegionSummary;
    ViewOpts.ShowInstantiationSummary = InstantiationSummary;
    ViewOpts.ExportSummaryOnly = SummaryOnly;
    ViewOpts.NumThreads = NumThreads;
    ViewOpts.CompilationDirectory = CompilationDirectory;

    return 0;
  };

  switch (Cmd) {
  case Show:
    return doShow(argc, argv, commandLineParser);
  case Report:
    return doReport(argc, argv, commandLineParser);
  case Export:
    return doExport(argc, argv, commandLineParser);
  }
  return 0;
}

int CodeCoverageTool::doShow(int argc, const char **argv,
                             CommandLineParserType commandLineParser) {

  cl::OptionCategory ViewCategory("Viewing options");

  cl::opt<bool> ShowLineExecutionCounts(
      "show-line-counts", cl::Optional,
      cl::desc("Show the execution counts for each line"), cl::init(true),
      cl::cat(ViewCategory));

  cl::opt<bool> ShowRegions(
      "show-regions", cl::Optional,
      cl::desc("Show the execution counts for each region"),
      cl::cat(ViewCategory));

  cl::opt<CoverageViewOptions::BranchOutputType> ShowBranches(
      "show-branches", cl::Optional,
      cl::desc("Show coverage for branch conditions"), cl::cat(ViewCategory),
      cl::values(clEnumValN(CoverageViewOptions::BranchOutputType::Count,
                            "count", "Show True/False counts"),
                 clEnumValN(CoverageViewOptions::BranchOutputType::Percent,
                            "percent", "Show True/False percent")),
      cl::init(CoverageViewOptions::BranchOutputType::Off));

  cl::opt<bool> ShowBestLineRegionsCounts(
      "show-line-counts-or-regions", cl::Optional,
      cl::desc("Show the execution counts for each line, or the execution "
               "counts for each region on lines that have multiple regions"),
      cl::cat(ViewCategory));

  cl::opt<bool> ShowExpansions("show-expansions", cl::Optional,
                               cl::desc("Show expanded source regions"),
                               cl::cat(ViewCategory));

  cl::opt<bool> ShowInstantiations("show-instantiations", cl::Optional,
                                   cl::desc("Show function instantiations"),
                                   cl::init(true), cl::cat(ViewCategory));

  cl::opt<std::string> ShowOutputDirectory(
      "output-dir", cl::init(""),
      cl::desc("Directory in which coverage information is written out"));
  cl::alias ShowOutputDirectoryA("o", cl::desc("Alias for --output-dir"),
                                 cl::aliasopt(ShowOutputDirectory));

  cl::opt<uint32_t> TabSize(
      "tab-size", cl::init(2),
      cl::desc(
          "Set tab expansion size for html coverage reports (default = 2)"));

  cl::opt<std::string> ProjectTitle(
      "project-title", cl::Optional,
      cl::desc("Set project title for the coverage report"));

  auto Err = commandLineParser(argc, argv);
  if (Err)
    return Err;

  if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) {
    error("Lcov format should be used with 'llvm-cov export'.");
    return 1;
  }

  ViewOpts.ShowLineNumbers = true;
  ViewOpts.ShowLineStats = ShowLineExecutionCounts.getNumOccurrences() != 0 ||
                           !ShowRegions || ShowBestLineRegionsCounts;
  ViewOpts.ShowRegionMarkers = ShowRegions || ShowBestLineRegionsCounts;
  ViewOpts.ShowExpandedRegions = ShowExpansions;
  ViewOpts.ShowBranchCounts =
      ShowBranches == CoverageViewOptions::BranchOutputType::Count;
  ViewOpts.ShowBranchPercents =
      ShowBranches == CoverageViewOptions::BranchOutputType::Percent;
  ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
  ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
  ViewOpts.TabSize = TabSize;
  ViewOpts.ProjectTitle = ProjectTitle;

  if (ViewOpts.hasOutputDirectory()) {
    if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
      error("Could not create output directory!", E.message());
      return 1;
    }
  }

  sys::fs::file_status Status;
  if (std::error_code EC = sys::fs::status(PGOFilename, Status)) {
    error("Could not read profile data!", EC.message());
    return 1;
  }

  auto ModifiedTime = Status.getLastModificationTime();
  std::string ModifiedTimeStr = to_string(ModifiedTime);
  size_t found = ModifiedTimeStr.rfind(':');
  ViewOpts.CreatedTimeStr = (found != std::string::npos)
                                ? "Created: " + ModifiedTimeStr.substr(0, found)
                                : "Created: " + ModifiedTimeStr;

  auto Coverage = load();
  if (!Coverage)
    return 1;

  auto Printer = CoveragePrinter::create(ViewOpts);

  if (SourceFiles.empty() && !HadSourceFiles)
    // Get the source files from the function coverage mapping.
    for (StringRef Filename : Coverage->getUniqueSourceFiles()) {
      if (!IgnoreFilenameFilters.matchesFilename(Filename))
        SourceFiles.push_back(std::string(Filename));
    }

  // Create an index out of the source files.
  if (ViewOpts.hasOutputDirectory()) {
    if (Error E = Printer->createIndexFile(SourceFiles, *Coverage, Filters)) {
      error("Could not create index file!", toString(std::move(E)));
      return 1;
    }
  }

  if (!Filters.empty()) {
    // Build the map of filenames to functions.
    std::map<llvm::StringRef, std::vector<const FunctionRecord *>>
        FilenameFunctionMap;
    for (const auto &SourceFile : SourceFiles)
      for (const auto &Function : Coverage->getCoveredFunctions(SourceFile))
        if (Filters.matches(*Coverage.get(), Function))
          FilenameFunctionMap[SourceFile].push_back(&Function);

    // Only print filter matching functions for each file.
    for (const auto &FileFunc : FilenameFunctionMap) {
      StringRef File = FileFunc.first;
      const auto &Functions = FileFunc.second;

      auto OSOrErr = Printer->createViewFile(File, /*InToplevel=*/false);
      if (Error E = OSOrErr.takeError()) {
        error("Could not create view file!", toString(std::move(E)));
        return 1;
      }
      auto OS = std::move(OSOrErr.get());

      bool ShowTitle = ViewOpts.hasOutputDirectory();
      for (const auto *Function : Functions) {
        auto FunctionView = createFunctionView(*Function, *Coverage);
        if (!FunctionView) {
          warning("Could not read coverage for '" + Function->Name + "'.");
          continue;
        }
        FunctionView->print(*OS.get(), /*WholeFile=*/false,
                            /*ShowSourceName=*/true, ShowTitle);
        ShowTitle = false;
      }

      Printer->closeViewFile(std::move(OS));
    }
    return 0;
  }

  // Show files
  bool ShowFilenames =
      (SourceFiles.size() != 1) || ViewOpts.hasOutputDirectory() ||
      (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML);

  ThreadPoolStrategy S = hardware_concurrency(ViewOpts.NumThreads);
  if (ViewOpts.NumThreads == 0) {
    // If NumThreads is not specified, create one thread for each input, up to
    // the number of hardware cores.
    S = heavyweight_hardware_concurrency(SourceFiles.size());
    S.Limit = true;
  }

  if (!ViewOpts.hasOutputDirectory() || S.ThreadsRequested == 1) {
    for (const std::string &SourceFile : SourceFiles)
      writeSourceFileView(SourceFile, Coverage.get(), Printer.get(),
                          ShowFilenames);
  } else {
    // In -output-dir mode, it's safe to use multiple threads to print files.
    ThreadPool Pool(S);
    for (const std::string &SourceFile : SourceFiles)
      Pool.async(&CodeCoverageTool::writeSourceFileView, this, SourceFile,
                 Coverage.get(), Printer.get(), ShowFilenames);
    Pool.wait();
  }

  return 0;
}

int CodeCoverageTool::doReport(int argc, const char **argv,
                               CommandLineParserType commandLineParser) {
  cl::opt<bool> ShowFunctionSummaries(
      "show-functions", cl::Optional, cl::init(false),
      cl::desc("Show coverage summaries for each function"));

  auto Err = commandLineParser(argc, argv);
  if (Err)
    return Err;

  if (ViewOpts.Format == CoverageViewOptions::OutputFormat::HTML) {
    error("HTML output for summary reports is not yet supported.");
    return 1;
  } else if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) {
    error("Lcov format should be used with 'llvm-cov export'.");
    return 1;
  }

  auto Coverage = load();
  if (!Coverage)
    return 1;

  CoverageReport Report(ViewOpts, *Coverage.get());
  if (!ShowFunctionSummaries) {
    if (SourceFiles.empty())
      Report.renderFileReports(llvm::outs(), IgnoreFilenameFilters);
    else
      Report.renderFileReports(llvm::outs(), SourceFiles);
  } else {
    if (SourceFiles.empty()) {
      error("Source files must be specified when -show-functions=true is "
            "specified");
      return 1;
    }

    Report.renderFunctionReports(SourceFiles, DC, llvm::outs());
  }
  return 0;
}

int CodeCoverageTool::doExport(int argc, const char **argv,
                               CommandLineParserType commandLineParser) {

  cl::OptionCategory ExportCategory("Exporting options");

  cl::opt<bool> SkipExpansions("skip-expansions", cl::Optional,
                               cl::desc("Don't export expanded source regions"),
                               cl::cat(ExportCategory));

  cl::opt<bool> SkipFunctions("skip-functions", cl::Optional,
                              cl::desc("Don't export per-function data"),
                              cl::cat(ExportCategory));

  auto Err = commandLineParser(argc, argv);
  if (Err)
    return Err;

  ViewOpts.SkipExpansions = SkipExpansions;
  ViewOpts.SkipFunctions = SkipFunctions;

  if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text &&
      ViewOpts.Format != CoverageViewOptions::OutputFormat::Lcov) {
    error("Coverage data can only be exported as textual JSON or an "
          "lcov tracefile.");
    return 1;
  }

  auto Coverage = load();
  if (!Coverage) {
    error("Could not load coverage information");
    return 1;
  }

  std::unique_ptr<CoverageExporter> Exporter;

  switch (ViewOpts.Format) {
  case CoverageViewOptions::OutputFormat::Text:
    Exporter = std::make_unique<CoverageExporterJson>(*Coverage.get(),
                                                       ViewOpts, outs());
    break;
  case CoverageViewOptions::OutputFormat::HTML:
    // Unreachable because we should have gracefully terminated with an error
    // above.
    llvm_unreachable("Export in HTML is not supported!");
  case CoverageViewOptions::OutputFormat::Lcov:
    Exporter = std::make_unique<CoverageExporterLcov>(*Coverage.get(),
                                                       ViewOpts, outs());
    break;
  }

  if (SourceFiles.empty())
    Exporter->renderRoot(IgnoreFilenameFilters);
  else
    Exporter->renderRoot(SourceFiles);

  return 0;
}

int showMain(int argc, const char *argv[]) {
  CodeCoverageTool Tool;
  return Tool.run(CodeCoverageTool::Show, argc, argv);
}

int reportMain(int argc, const char *argv[]) {
  CodeCoverageTool Tool;
  return Tool.run(CodeCoverageTool::Report, argc, argv);
}

int exportMain(int argc, const char *argv[]) {
  CodeCoverageTool Tool;
  return Tool.run(CodeCoverageTool::Export, argc, argv);
}
