[llvm-cov] Add support for loading coverage from multiple objects
authorVedant Kumar <vsk@apple.com>
Tue, 25 Oct 2016 17:40:55 +0000 (17:40 +0000)
committerVedant Kumar <vsk@apple.com>
Tue, 25 Oct 2016 17:40:55 +0000 (17:40 +0000)
Differential Revision: https://reviews.llvm.org/D25086

llvm-svn: 285088

llvm/docs/CommandGuide/llvm-cov.rst
llvm/test/tools/llvm-cov/load-multiple-objects.test [new file with mode: 0644]
llvm/test/tools/llvm-cov/universal-binary.c
llvm/tools/llvm-cov/CodeCoverage.cpp

index 3542489..4c0354c 100644 (file)
@@ -167,14 +167,14 @@ SHOW COMMAND
 SYNOPSIS
 ^^^^^^^^
 
-:program:`llvm-cov show` [*options*] -instr-profile *PROFILE* *BIN* [*SOURCES*]
+:program:`llvm-cov show` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] [*SOURCES*]
 
 DESCRIPTION
 ^^^^^^^^^^^
 
-The :program:`llvm-cov show` command shows line by line coverage of a binary
-*BIN* using the profile data *PROFILE*. It can optionally be filtered to only
-show the coverage for the files listed in *SOURCES*.
+The :program:`llvm-cov show` command shows line by line coverage of the
+binaries *BIN*,...  using the profile data *PROFILE*. It can optionally be
+filtered to only show the coverage for the files listed in *SOURCES*.
 
 To use :program:`llvm-cov show`, you need a program that is compiled with
 instrumentation to emit profile and coverage data. To build such a program with
@@ -183,7 +183,7 @@ flags. If linking with the ``clang`` driver, pass ``-fprofile-instr-generate``
 to the link stage to make sure the necessary runtime libraries are linked in.
 
 The coverage information is stored in the built executable or library itself,
-and this is what you should pass to :program:`llvm-cov show` as the *BIN*
+and this is what you should pass to :program:`llvm-cov show` as a *BIN*
 argument. The profile data is generated by running this instrumented program
 normally. When the program exits it will write out a raw profile file,
 typically called ``default.profraw``, which can be converted to a format that
@@ -292,14 +292,14 @@ REPORT COMMAND
 SYNOPSIS
 ^^^^^^^^
 
-:program:`llvm-cov report` [*options*] -instr-profile *PROFILE* *BIN* [*SOURCES*]
+:program:`llvm-cov report` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]] [*SOURCES*]
 
 DESCRIPTION
 ^^^^^^^^^^^
 
-The :program:`llvm-cov report` command displays a summary of the coverage of a
-binary *BIN* using the profile data *PROFILE*. It can optionally be filtered to
-only show the coverage for the files listed in *SOURCES*.
+The :program:`llvm-cov report` command displays a summary of the coverage of
+the binaries *BIN*,... using the profile data *PROFILE*. It can optionally be
+filtered to only show the coverage for the files listed in *SOURCES*.
 
 If no source files are provided, a summary line is printed for each file in the
 coverage data. If any files are provided, summaries are shown for each function
@@ -332,13 +332,13 @@ EXPORT COMMAND
 SYNOPSIS
 ^^^^^^^^
 
-:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN*
+:program:`llvm-cov export` [*options*] -instr-profile *PROFILE* *BIN* [*-object BIN,...*] [[*-object BIN*]]
 
 DESCRIPTION
 ^^^^^^^^^^^
 
 The :program:`llvm-cov export` command exports regions, functions, expansions,
-and summaries of the coverage of a binary *BIN* using the profile data
+and summaries of the coverage of the binaries *BIN*,... using the profile data
 *PROFILE* as JSON.
 
 For information on compiling programs for coverage and generating profile data,
diff --git a/llvm/test/tools/llvm-cov/load-multiple-objects.test b/llvm/test/tools/llvm-cov/load-multiple-objects.test
new file mode 100644 (file)
index 0000000..55fed31
--- /dev/null
@@ -0,0 +1,11 @@
+// RUN: llvm-profdata merge %S/Inputs/multiple-files.proftext %S/Inputs/highlightedRanges.profdata -o %t.profdata
+
+// RUN: llvm-cov report -object %S/Inputs/multiple-files.covmapping -instr-profile %t.profdata | FileCheck %s -check-prefix=OBJ1
+
+// RUN: llvm-cov report %S/Inputs/multiple-files.covmapping -object %S/Inputs/highlightedRanges.covmapping -instr-profile %t.profdata | FileCheck %s -check-prefixes=OBJ1,OBJ2
+
+// OBJ2: showHighlightedRanges.cpp
+// OBJ1: f2.c
+// OBJ1: f4.c
+// OBJ1: f3.c
+// OBJ1: f1.c
index b398d39..1b15f98 100644 (file)
@@ -12,4 +12,4 @@ int main(int argc, const char *argv[]) {}
 // WRONG-ARCH: Failed to load coverage
 
 // RUN: not llvm-cov report -instr-profile %t.profdata 2>&1 | FileCheck --check-prefix=MISSING-BINARY %s
-// MISSING-BINARY: 1 positional argument: See:
+// MISSING-BINARY: No filenames specified!
index 6bd61d3..81e55ae 100644 (file)
@@ -116,7 +116,7 @@ private:
   int export_(int argc, const char **argv,
               CommandLineParserType commandLineParser);
 
-  std::string ObjectFilename;
+  std::vector<StringRef> ObjectFilenames;
   CoverageViewOptions ViewOpts;
   CoverageFiltersMatchAll Filters;
 
@@ -325,13 +325,15 @@ static bool modifiedTimeGT(StringRef LHS, StringRef RHS) {
 }
 
 std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
-  if (modifiedTimeGT(ObjectFilename, PGOFilename))
-    warning("profile data may be out of date - object is newer",
-            ObjectFilename);
+  for (StringRef ObjectFilename : ObjectFilenames)
+    if (modifiedTimeGT(ObjectFilename, PGOFilename))
+      warning("profile data may be out of date - object is newer",
+              ObjectFilename);
   auto CoverageOrErr =
-      CoverageMapping::load(ObjectFilename, PGOFilename, CoverageArch);
+      CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArch);
   if (Error E = CoverageOrErr.takeError()) {
-    error("Failed to load coverage: " + toString(std::move(E)), ObjectFilename);
+    error("Failed to load coverage: " + toString(std::move(E)),
+          join(ObjectFilenames.begin(), ObjectFilenames.end(), ", "));
     return nullptr;
   }
   auto Coverage = std::move(CoverageOrErr.get());
@@ -484,9 +486,12 @@ void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
 }
 
 int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
-  cl::opt<std::string, true> ObjectFilename(
-      cl::Positional, cl::Required, cl::location(this->ObjectFilename),
-      cl::desc("Covered executable or object file."));
+  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::CommaSeparated);
 
   cl::list<std::string> InputSourceFiles(
       cl::Positional, cl::desc("<Source files>"), cl::ZeroOrMore);
@@ -568,6 +573,15 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
     ViewOpts.Debug = DebugDump;
     CompareFilenamesOnly = FilenameEquivalence;
 
+    if (!CovFilename.empty())
+      ObjectFilenames.emplace_back(CovFilename);
+    for (const std::string &Filename : CovFilenames)
+      ObjectFilenames.emplace_back(Filename);
+    if (ObjectFilenames.empty()) {
+      error("No filenames specified!");
+      ::exit(1);
+    }
+
     ViewOpts.Format = Format;
     switch (ViewOpts.Format) {
     case CoverageViewOptions::OutputFormat::Text: