keith created this revision.
keith added reviewers: vsk, arphaman, rnk.
Herald added a subscriber: dexonsmith.
Herald added a project: clang.
keith added a comment.

Open question: I don't know how all the toolchains fit together, but I noticed 
that only Clang.cpp handles -fmacro-prefix-map, but Clang.cpp, FreeBSD.cpp, and 
Gnu.cpp all handle -fdebug-prefix-map. I wasn't sure which pattern I should 
follow here, so right now this only adds the handling to Clang.cpp, please let 
me know if that's not appropriate in this case!


This flag allows you to re-write absolute paths in coverage data analogous to 
-fdebug-prefix-map. This flag is also implied by -ffile-prefix-map.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83154

Files:
  clang/include/clang/Basic/CodeGenOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/CoverageMappingGen.cpp
  clang/lib/CodeGen/CoverageMappingGen.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CoverageMapping/coverage-prefix-map.c
  clang/test/Driver/debug-prefix-map.c

Index: clang/test/Driver/debug-prefix-map.c
===================================================================
--- clang/test/Driver/debug-prefix-map.c
+++ clang/test/Driver/debug-prefix-map.c
@@ -1,28 +1,39 @@
 // RUN: %clang -### -fdebug-prefix-map=old %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-INVALID
 // RUN: %clang -### -fmacro-prefix-map=old %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-INVALID
+// RUN: %clang -### -fcoverage-prefix-map=old %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-INVALID
 // RUN: %clang -### -ffile-prefix-map=old %s 2>&1 | FileCheck %s -check-prefix CHECK-FILE-INVALID
 
 // RUN: %clang -### -fdebug-prefix-map=old=new %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-SIMPLE
 // RUN: %clang -### -fmacro-prefix-map=old=new %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-SIMPLE
+// RUN: %clang -### -fcoverage-prefix-map=old=new %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-SIMPLE
 // RUN: %clang -### -ffile-prefix-map=old=new %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-SIMPLE
 // RUN: %clang -### -ffile-prefix-map=old=new %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-SIMPLE
+// RUN: %clang -### -ffile-prefix-map=old=new %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-SIMPLE
 
 // RUN: %clang -### -fdebug-prefix-map=old=n=ew %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-COMPLEX
 // RUN: %clang -### -fmacro-prefix-map=old=n=ew %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-COMPLEX
+// RUN: %clang -### -fcoverage-prefix-map=old=n=ew %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-COMPLEX
 // RUN: %clang -### -ffile-prefix-map=old=n=ew %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-COMPLEX
 // RUN: %clang -### -ffile-prefix-map=old=n=ew %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-COMPLEX
+// RUN: %clang -### -ffile-prefix-map=old=n=ew %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-COMPLEX
 
 // RUN: %clang -### -fdebug-prefix-map=old= %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-EMPTY
 // RUN: %clang -### -fmacro-prefix-map=old= %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-EMPTY
+// RUN: %clang -### -fcoverage-prefix-map=old= %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-EMPTY
 // RUN: %clang -### -ffile-prefix-map=old= %s 2>&1 | FileCheck %s -check-prefix CHECK-DEBUG-EMPTY
 // RUN: %clang -### -ffile-prefix-map=old= %s 2>&1 | FileCheck %s -check-prefix CHECK-MACRO-EMPTY
+// RUN: %clang -### -ffile-prefix-map=old= %s 2>&1 | FileCheck %s -check-prefix CHECK-COVERAGE-EMPTY
 
 // CHECK-DEBUG-INVALID: error: invalid argument 'old' to -fdebug-prefix-map
 // CHECK-MACRO-INVALID: error: invalid argument 'old' to -fmacro-prefix-map
+// CHECK-COVERAGE-INVALID: error: invalid argument 'old' to -fcoverage-prefix-map
 // CHECK-FILE-INVALID: error: invalid argument 'old' to -ffile-prefix-map
 // CHECK-DEBUG-SIMPLE: fdebug-prefix-map=old=new
 // CHECK-MACRO-SIMPLE: fmacro-prefix-map=old=new
+// CHECK-COVERAGE-SIMPLE: fcoverage-prefix-map=old=new
 // CHECK-DEBUG-COMPLEX: fdebug-prefix-map=old=n=ew
 // CHECK-MACRO-COMPLEX: fmacro-prefix-map=old=n=ew
+// CHECK-COVERAGE-COMPLEX: fcoverage-prefix-map=old=n=ew
 // CHECK-DEBUG-EMPTY: fdebug-prefix-map=old=
 // CHECK-MACRO-EMPTY: fmacro-prefix-map=old=
+// CHECK-COVERAGE-EMPTY: fcoverage-prefix-map=old=
Index: clang/test/CoverageMapping/coverage-prefix-map.c
===================================================================
--- /dev/null
+++ clang/test/CoverageMapping/coverage-prefix-map.c
@@ -0,0 +1,14 @@
+// %s expands to an absolute path, so to test relative paths we need to create a
+// clean directory, put the source there, and cd into it.
+// RUN: rm -rf %t
+// RUN: mkdir -p %t/root/nested
+// RUN: echo "void f1() {}" > %t/root/nested/coverage-prefix-map.c
+// RUN: cd %t/root
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name coverage-prefix-map.c nested/coverage-prefix-map.c -o - | FileCheck --check-prefix=ABSOLUTE %s
+//
+// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\01.*root.*nested.*coverage-prefix-map\.c}}
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name coverage-prefix-map.c nested/coverage-prefix-map.c -fcoverage-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=COVERAGE-PREFIX-MAP %s --implicit-check-not=root
+//
+// COVERAGE-PREFIX-MAP: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\}}nested{{.*coverage-prefix-map\.c}}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -774,6 +774,12 @@
         {std::string(Split.first), std::string(Split.second)});
   }
 
+  for (const auto &Arg : Args.getAllArgValues(OPT_fcoverage_prefix_map_EQ)) {
+    auto Split = StringRef(Arg).split('=');
+    Opts.CoveragePrefixMap.insert(
+        {std::string(Split.first), std::string(Split.second)});
+  }
+
   if (const Arg *A =
           Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists))
     Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists;
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -661,6 +661,21 @@
   }
 }
 
+/// Add a CC1 and CC1AS option to specify the coverage file path prefix map.
+static void addCoveragePrefixMapArg(const Driver &D, const ArgList &Args,
+                                    ArgStringList &CmdArgs) {
+  for (const Arg *A : Args.filtered(options::OPT_ffile_prefix_map_EQ,
+                                    options::OPT_fcoverage_prefix_map_EQ)) {
+    StringRef Map = A->getValue();
+    if (Map.find('=') == StringRef::npos)
+      D.Diag(diag::err_drv_invalid_argument_to_option)
+          << Map << A->getOption().getName();
+    else
+      CmdArgs.push_back(Args.MakeArgString("-fcoverage-prefix-map=" + Map));
+    A->claim();
+  }
+}
+
 /// Vectorize at all optimization levels greater than 1 except for -Oz.
 /// For -Oz the loop vectorizer is disabled, while the slp vectorizer is
 /// enabled.
@@ -1373,6 +1388,7 @@
   }
 
   addMacroPrefixMapArg(D, Args, CmdArgs);
+  addCoveragePrefixMapArg(D, Args, CmdArgs);
 }
 
 // FIXME: Move to target hook.
Index: clang/lib/CodeGen/CoverageMappingGen.h
===================================================================
--- clang/lib/CodeGen/CoverageMappingGen.h
+++ clang/lib/CodeGen/CoverageMappingGen.h
@@ -60,14 +60,16 @@
   llvm::SmallDenseMap<const FileEntry *, unsigned, 8> FileEntries;
   std::vector<llvm::Constant *> FunctionNames;
   std::vector<FunctionInfo> FunctionRecords;
+  std::map<std::string, std::string> CoveragePrefixMap;
+
+  std::string normalizeFilename(StringRef Filename);
 
   /// Emit a function record.
   void emitFunctionMappingRecord(const FunctionInfo &Info,
                                  uint64_t FilenamesRef);
 
 public:
-  CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
-      : CGM(CGM), SourceInfo(SourceInfo) {}
+  CoverageMappingModuleGen(CodeGenModule &CGM, CoverageSourceInfo &SourceInfo);
 
   CoverageSourceInfo &getSourceInfo() const {
     return SourceInfo;
Index: clang/lib/CodeGen/CoverageMappingGen.cpp
===================================================================
--- clang/lib/CodeGen/CoverageMappingGen.cpp
+++ clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1279,13 +1279,6 @@
   }
 };
 
-std::string normalizeFilename(StringRef Filename) {
-  llvm::SmallString<256> Path(Filename);
-  llvm::sys::fs::make_absolute(Path);
-  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
-  return std::string(Path);
-}
-
 } // end anonymous namespace
 
 static void dump(llvm::raw_ostream &OS, StringRef FunctionName,
@@ -1318,6 +1311,23 @@
   }
 }
 
+CoverageMappingModuleGen::CoverageMappingModuleGen(
+    CodeGenModule &CGM, CoverageSourceInfo &SourceInfo)
+    : CGM(CGM), SourceInfo(SourceInfo) {
+  CoveragePrefixMap = CGM.getCodeGenOpts().CoveragePrefixMap;
+}
+
+std::string CoverageMappingModuleGen::normalizeFilename(StringRef Filename) {
+  llvm::SmallString<256> Path(Filename);
+  llvm::sys::fs::make_absolute(Path);
+  llvm::sys::path::remove_dots(Path, /*remove_dot_dot=*/true);
+  for (const auto &Entry : CoveragePrefixMap) {
+    if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
+      break;
+  }
+  return Path.str().str();
+}
+
 static std::string getInstrProfSection(const CodeGenModule &CGM,
                                        llvm::InstrProfSectKind SK) {
   return llvm::getInstrProfSectionName(
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2061,6 +2061,10 @@
   : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>,
     Flags<[CC1Option,CC1AsOption]>,
     HelpText<"remap file source paths in debug info">;
+def fcoverage_prefix_map_EQ
+  : Joined<["-"], "fcoverage-prefix-map=">, Group<f_Group>,
+    Flags<[CC1Option,CC1AsOption]>,
+    HelpText<"remap file source paths in coverage info">;
 def ffile_prefix_map_EQ
   : Joined<["-"], "ffile-prefix-map=">, Group<f_Group>,
     HelpText<"remap file source paths in debug info and predefined preprocessor macros">;
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -167,6 +167,7 @@
   std::string RecordCommandLine;
 
   std::map<std::string, std::string> DebugPrefixMap;
+  std::map<std::string, std::string> CoveragePrefixMap;
 
   /// The ABI to use for passing floating point arguments.
   std::string FloatABI;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to