[llvm] 5042e1e - [llvm-cov] Allow multiple remaps in --path-equivalence

Keith Smiley via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 23 15:28:08 PDT 2023


Author: Tomas Camin
Date: 2023-08-23T15:27:56-07:00
New Revision: 5042e1e56d39a02517abecbe00e72eea698d309a

URL: https://github.com/llvm/llvm-project/commit/5042e1e56d39a02517abecbe00e72eea698d309a
DIFF: https://github.com/llvm/llvm-project/commit/5042e1e56d39a02517abecbe00e72eea698d309a.diff

LOG: [llvm-cov] Allow multiple remaps in --path-equivalence

Previously the --path-equivalence parameter would allow to specify a single remap pair (coverage data path - local source file path). This patch changes this allowing to pass as many remaps as needed.

Reviewed By: keith

Differential Revision: https://reviews.llvm.org/D154223

Added: 
    llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.covmapping
    llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.proftext
    llvm/test/tools/llvm-cov/multiple-path_equivalence.test

Modified: 
    llvm/docs/CommandGuide/llvm-cov.rst
    llvm/test/tools/llvm-cov/path_equivalence.c
    llvm/tools/llvm-cov/CodeCoverage.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/docs/CommandGuide/llvm-cov.rst b/llvm/docs/CommandGuide/llvm-cov.rst
index 44bb135371512a..792f9629dbfbd0 100644
--- a/llvm/docs/CommandGuide/llvm-cov.rst
+++ b/llvm/docs/CommandGuide/llvm-cov.rst
@@ -340,7 +340,11 @@ OPTIONS
 
  Map the paths in the coverage data to local source file paths. This allows you
  to generate the coverage data on one machine, and then use llvm-cov on a
- 
diff erent machine where you have the same files on a 
diff erent path.
+ 
diff erent machine where you have the same files on a 
diff erent path. Multiple
+ `-path-equivalence` arguments can be passed to specify 
diff erent mappings. Each
+ argument consists of a source path `<from>` and its corresponding local path `<to>`.
+ The mappings are applied in the order they are specified. If multiple mappings can
+ be applied to a single path, the first mapping encountered is used.
 
 .. option:: -coverage-watermark=<high>,<low>
 

diff  --git a/llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.covmapping b/llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.covmapping
new file mode 100644
index 00000000000000..3e229a8c301a75
Binary files /dev/null and b/llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.covmapping 
diff er

diff  --git a/llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.proftext b/llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.proftext
new file mode 100644
index 00000000000000..1be93b71b77a7f
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/multiple-path_equivalence.proftext
@@ -0,0 +1,19 @@
+f1
+0x0
+1
+1
+
+f2
+0x0
+1
+1
+
+f3
+0x0
+1
+1
+
+f4
+0x0
+1
+1

diff  --git a/llvm/test/tools/llvm-cov/multiple-path_equivalence.test b/llvm/test/tools/llvm-cov/multiple-path_equivalence.test
new file mode 100644
index 00000000000000..1c8ec9a82a81cf
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/multiple-path_equivalence.test
@@ -0,0 +1,32 @@
+# multiple-path_equivalence.covmapping contains references to 4 files:
+# /tmp/coverage/main.c
+# /tmp/coverage/f1.c
+# /tmp/coverage/a/f2.c
+# /tmp/coverage/b/f3.c
+# /tmp/coverage/b/c/f4.c
+
+# Setup
+// RUN: touch %/T/main.c; touch %/T/f1.c; touch %/T/f2.c; touch %/T/f3.c; touch %/T/f4.c
+// RUN: llvm-profdata merge %S/Inputs/multiple-path_equivalence.proftext -o %t.profdata
+
+# Make sure that remapping follows the specified order with the first matching entry being used first (f4 comes before f3)
+// RUN: llvm-cov show %S/Inputs/multiple-path_equivalence.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp/coverage/a,%/T -path-equivalence=/tmp/coverage/b/c,%/T -path-equivalence=/tmp/coverage/b,%/T -path-equivalence=/tmp/coverage,%/T 2>&1 | FileCheck %s
+
+// CHECK-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}main.c:
+// CHECK-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}f1.c:
+// CHECK-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}a{{/|\\}}f2.c:
+// CHECK-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}b{{/|\\}}f3.c:
+// CHECK-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}b{{/|\\}}c{{/|\\}}f4.c:
+// CHECK-NOT: isn't covered.
+
+# Make sure remapping follows the specified order by proving paths in an overriding order (f4 comes after f3)
+// RUN: llvm-cov show %S/Inputs/multiple-path_equivalence.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp/coverage/a,%/T -path-equivalence=/tmp/coverage/b,%/T -path-equivalence=/tmp/coverage/b/c,%/T -path-equivalence=/tmp/coverage,%/T 2>&1 | FileCheck %s -check-prefix=OVERRIDING_ORDER
+
+// OVERRIDING_ORDER-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}main.c:
+// OVERRIDING_ORDER-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}f1.c:
+// OVERRIDING_ORDER-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}a{{/|\\}}f2.c:
+// OVERRIDING_ORDER-DAG: {{/|\\}}tmp{{/|\\}}coverage{{/|\\}}b{{/|\\}}f3.c:
+// OVERRIDING_ORDER-DAG: warning: The file '{{/|\\}}tmp{{/|\\}}coverage{{/|\\}}b{{/|\\}}c{{/|\\}}f4.c' isn't covered.
+
+// RUN: not llvm-cov show %S/Inputs/multiple-path_equivalence.covmapping -instr-profile=%t.profdata -path-equivalence=/tmp/coverage/a,%/T -path-equivalence=/tmp/coverage/b, -path-equivalence=/tmp/coverage/b/c,%/T -path-equivalence=/tmp/coverage,%/T 2>&1 | FileCheck %s -check-prefix=EMPTY_PATH
+// EMPTY_PATH: must be in format 'from,to'
\ No newline at end of file

diff  --git a/llvm/test/tools/llvm-cov/path_equivalence.c b/llvm/test/tools/llvm-cov/path_equivalence.c
index 26a35b78d2d743..38422ce5600842 100644
--- a/llvm/test/tools/llvm-cov/path_equivalence.c
+++ b/llvm/test/tools/llvm-cov/path_equivalence.c
@@ -5,3 +5,6 @@ int main() {} // CHECK: [[@LINE]]|      1|int main() {}
 
 // RUN: not llvm-cov show --instr-profile=/dev/null -path-equivalence=foo /dev/null 2>&1 | FileCheck --check-prefix=INVALID %s
 // INVALID: error: -path-equivalence: invalid argument 'foo', must be in format 'from,to'
+
+// RUN: not llvm-cov show --instr-profile=/dev/null -path-equivalence=,foo /dev/null 2>&1 | FileCheck --check-prefix=EMPTY_PATH %s
+// EMPTY_PATH: error: -path-equivalence: invalid argument ',foo', must be in format 'from,to'

diff  --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 02448dcd31a161..3992dfa8932c35 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -162,7 +162,8 @@ class CodeCoverageTool {
 
   /// The coverage data path to be remapped from, and the source path to be
   /// remapped to, when using -path-equivalence.
-  std::optional<std::pair<std::string, std::string>> PathRemapping;
+  std::optional<std::vector<std::pair<std::string, std::string>>>
+      PathRemappings;
 
   /// File status cache used when finding the same file.
   StringMap<std::optional<sys::fs::file_status>> FileStatusCache;
@@ -228,7 +229,7 @@ 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)
+    if (PathRemappings)
       addCollectedPath(Path);
     else
       warning("Source file doesn't exist, proceeded by ignoring it.", Path);
@@ -474,7 +475,7 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
 }
 
 void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
-  if (!PathRemapping)
+  if (!PathRemappings)
     return;
 
   // Convert remapping paths to native paths with trailing seperators.
@@ -488,17 +489,23 @@ void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
       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();
+  for (std::pair<std::string, std::string> &PathRemapping : *PathRemappings) {
+    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()) {
+      if (RemappedFilenames.count(Filename) == 1)
+        continue;
+
+      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();
+      }
     }
   }
 
@@ -674,7 +681,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
                             "lcov tracefile output")),
       cl::init(CoverageViewOptions::OutputFormat::Text));
 
-  cl::opt<std::string> PathRemap(
+  cl::list<std::string> PathRemaps(
       "path-equivalence", cl::Optional,
       cl::desc("<from>,<to> Map coverage data paths to local source file "
                "paths"));
@@ -812,19 +819,23 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
       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;
+    if (!PathRemaps.empty()) {
+      std::vector<std::pair<std::string, std::string>> Remappings;
+
+      for (const std::string &PathRemap : PathRemaps) {
+        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;
+        }
+
+        Remappings.push_back(
+            {std::string(EquivPair.first), std::string(EquivPair.second)});
       }
 
-      PathRemapping = {std::string(EquivPair.first),
-                       std::string(EquivPair.second)};
+      PathRemappings = Remappings;
     }
 
     // If a demangler is supplied, check if it exists and register it.


        


More information about the llvm-commits mailing list