phosek updated this revision to Diff 322609.
phosek retitled this revision from "[CoverageMapping] Don't absolutize source 
paths" to "Store compilation dir separately in coverage mapping".
phosek edited the summary of this revision.
Herald added subscribers: llvm-commits, dexonsmith, dang, sstefan1, hiraditya.
Herald added a reviewer: jdoerfert.
Herald added a reviewer: jansvoboda11.
Herald added a project: LLVM.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95753/new/

https://reviews.llvm.org/D95753

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/test/CoverageMapping/abspath.cpp
  clang/test/Profile/profile-prefix-map.c
  llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
  llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp

Index: llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
===================================================================
--- llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -97,9 +97,7 @@
   return Error::success();
 }
 
-Error RawCoverageFilenamesReader::read(
-    CovMapVersion Version,
-    BinaryCoverageReader::DecompressedData &Decompressed) {
+Error RawCoverageFilenamesReader::read(CovMapVersion Version) {
   uint64_t NumFilenames;
   if (auto Err = readSize(NumFilenames))
     return Err;
@@ -124,11 +122,8 @@
       return make_error<CoverageMapError>(
           coveragemap_error::decompression_failed);
 
-    // Allocate memory for the decompressed filenames. Transfer ownership of
-    // the memory to BinaryCoverageReader.
-    auto DecompressedStorage = std::make_unique<SmallVector<char, 0>>();
-    SmallVectorImpl<char> &StorageBuf = *DecompressedStorage.get();
-    Decompressed.push_back(std::move(DecompressedStorage));
+    // Allocate memory for the decompressed filenames.
+    SmallVector<char, 0> StorageBuf;
 
     // Read compressed filenames.
     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
@@ -150,13 +145,24 @@
 }
 
 Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) {
-  // Read uncompressed filenames.
-  for (size_t I = 0; I < NumFilenames; ++I) {
+  StringRef CWD;
+  if (auto Err = readString(CWD))
+    return Err;
+  Filenames.push_back(CWD.str());
+
+  for (size_t I = 1; I < NumFilenames; ++I) {
     StringRef Filename;
     if (auto Err = readString(Filename))
       return Err;
-    Filenames.push_back(Filename);
+    if (sys::path::is_absolute(Filename)) {
+      Filenames.push_back(Filename.str());
+    } else {
+      SmallString<256> P(CWD);
+      llvm::sys::path::append(P, Filename);
+      Filenames.push_back(static_cast<std::string>(P));
+    }
   }
+
   return Error::success();
 }
 
@@ -481,9 +487,8 @@
   //
   // Returns a pointer to the next \c CovHeader if it exists, or to an address
   // greater than \p CovEnd if not.
-  virtual Expected<const char *>
-  readCoverageHeader(const char *CovBuf, const char *CovBufEnd,
-                     BinaryCoverageReader::DecompressedData &Decompressed) = 0;
+  virtual Expected<const char *> readCoverageHeader(const char *CovBuf,
+                                                    const char *CovBufEnd) = 0;
 
   // Read function records.
   //
@@ -505,7 +510,7 @@
   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
   get(CovMapVersion Version, InstrProfSymtab &P,
       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
-      std::vector<StringRef> &F);
+      std::vector<std::string> &F);
 };
 
 // A class for reading coverage mapping function records for a module.
@@ -519,7 +524,7 @@
   // in \c Records.
   DenseMap<NameRefType, size_t> FunctionRecords;
   InstrProfSymtab &ProfileNames;
-  std::vector<StringRef> &Filenames;
+  std::vector<std::string> &Filenames;
   std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
 
   // Maps a hash of the filenames in a TU to a \c FileRange. The range
@@ -579,14 +584,13 @@
   VersionedCovMapFuncRecordReader(
       InstrProfSymtab &P,
       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
-      std::vector<StringRef> &F)
+      std::vector<std::string> &F)
       : ProfileNames(P), Filenames(F), Records(R) {}
 
   ~VersionedCovMapFuncRecordReader() override = default;
 
-  Expected<const char *> readCoverageHeader(
-      const char *CovBuf, const char *CovBufEnd,
-      BinaryCoverageReader::DecompressedData &Decompressed) override {
+  Expected<const char *> readCoverageHeader(const char *CovBuf,
+                                            const char *CovBufEnd) override {
     using namespace support;
 
     if (CovBuf + sizeof(CovMapHeader) > CovBufEnd)
@@ -615,7 +619,7 @@
     size_t FilenamesBegin = Filenames.size();
     StringRef FilenameRegion(CovBuf, FilenamesSize);
     RawCoverageFilenamesReader Reader(FilenameRegion, Filenames);
-    if (auto Err = Reader.read(Version, Decompressed))
+    if (auto Err = Reader.read(Version))
       return std::move(Err);
     CovBuf += FilenamesSize;
     FilenameRange FileRange(FilenamesBegin, Filenames.size() - FilenamesBegin);
@@ -721,7 +725,7 @@
 Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
     CovMapVersion Version, InstrProfSymtab &P,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
-    std::vector<StringRef> &F) {
+    std::vector<std::string> &F) {
   using namespace coverage;
 
   switch (Version) {
@@ -755,8 +759,7 @@
 static Error readCoverageMappingData(
     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
-    std::vector<StringRef> &Filenames,
-    BinaryCoverageReader::DecompressedData &Decompressed) {
+    std::vector<std::string> &Filenames) {
   using namespace coverage;
 
   // Read the records in the coverage data section.
@@ -782,8 +785,7 @@
     // header.
     //
     // Return a pointer to the next coverage header.
-    auto NextOrErr =
-        Reader->readCoverageHeader(CovBuf, CovBufEnd, Decompressed);
+    auto NextOrErr = Reader->readCoverageHeader(CovBuf, CovBufEnd);
     if (auto E = NextOrErr.takeError())
       return E;
     CovBuf = NextOrErr.get();
@@ -810,25 +812,23 @@
     if (Error E =
             readCoverageMappingData<uint32_t, support::endianness::little>(
                 Reader->ProfileNames, Coverage, FuncRecordsRef,
-                Reader->MappingRecords, Reader->Filenames,
-                Reader->Decompressed))
+                Reader->MappingRecords, Reader->Filenames))
       return std::move(E);
   } else if (BytesInAddress == 4 && Endian == support::endianness::big) {
     if (Error E = readCoverageMappingData<uint32_t, support::endianness::big>(
             Reader->ProfileNames, Coverage, FuncRecordsRef,
-            Reader->MappingRecords, Reader->Filenames, Reader->Decompressed))
+            Reader->MappingRecords, Reader->Filenames))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == support::endianness::little) {
     if (Error E =
             readCoverageMappingData<uint64_t, support::endianness::little>(
                 Reader->ProfileNames, Coverage, FuncRecordsRef,
-                Reader->MappingRecords, Reader->Filenames,
-                Reader->Decompressed))
+                Reader->MappingRecords, Reader->Filenames))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == support::endianness::big) {
     if (Error E = readCoverageMappingData<uint64_t, support::endianness::big>(
             Reader->ProfileNames, Coverage, FuncRecordsRef,
-            Reader->MappingRecords, Reader->Filenames, Reader->Decompressed))
+            Reader->MappingRecords, Reader->Filenames))
       return std::move(E);
   } else
     return make_error<CoverageMapError>(coveragemap_error::malformed);
@@ -1075,10 +1075,9 @@
   Expressions.clear();
   MappingRegions.clear();
   auto &R = MappingRecords[CurrentRecord];
-  RawCoverageMappingReader Reader(
-      R.CoverageMapping,
-      makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
-      FunctionsFilenames, Expressions, MappingRegions);
+  auto F = makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize);
+  RawCoverageMappingReader Reader(R.CoverageMapping, F, FunctionsFilenames,
+                                  Expressions, MappingRegions);
   if (auto Err = Reader.read())
     return Err;
 
Index: llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
===================================================================
--- llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -125,14 +125,14 @@
 
 /// Reader for the raw coverage mapping data.
 class RawCoverageMappingReader : public RawCoverageReader {
-  ArrayRef<StringRef> TranslationUnitFilenames;
+  ArrayRef<std::string> &TranslationUnitFilenames;
   std::vector<StringRef> &Filenames;
   std::vector<CounterExpression> &Expressions;
   std::vector<CounterMappingRegion> &MappingRegions;
 
 public:
   RawCoverageMappingReader(StringRef MappingData,
-                           ArrayRef<StringRef> TranslationUnitFilenames,
+                           ArrayRef<std::string> &TranslationUnitFilenames,
                            std::vector<StringRef> &Filenames,
                            std::vector<CounterExpression> &Expressions,
                            std::vector<CounterMappingRegion> &MappingRegions)
@@ -174,10 +174,8 @@
           FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {}
   };
 
-  using DecompressedData = std::vector<std::unique_ptr<SmallVector<char, 0>>>;
-
 private:
-  std::vector<StringRef> Filenames;
+  std::vector<std::string> Filenames;
   std::vector<ProfileMappingRecord> MappingRecords;
   InstrProfSymtab ProfileNames;
   size_t CurrentRecord = 0;
@@ -190,10 +188,6 @@
   // D69471, which can split up function records into multiple sections on ELF.
   std::string FuncRecords;
 
-  // Used to tie the lifetimes of decompressed strings to the lifetime of this
-  // BinaryCoverageReader instance.
-  DecompressedData Decompressed;
-
   BinaryCoverageReader(std::string &&FuncRecords)
       : FuncRecords(std::move(FuncRecords)) {}
 
@@ -216,20 +210,20 @@
 
 /// Reader for the raw coverage filenames.
 class RawCoverageFilenamesReader : public RawCoverageReader {
-  std::vector<StringRef> &Filenames;
+  std::vector<std::string> &Filenames;
 
   // Read an uncompressed sequence of filenames.
   Error readUncompressed(uint64_t NumFilenames);
 
 public:
-  RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames)
+  RawCoverageFilenamesReader(StringRef Data,
+                             std::vector<std::string> &Filenames)
       : RawCoverageReader(Data), Filenames(Filenames) {}
   RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete;
   RawCoverageFilenamesReader &
   operator=(const RawCoverageFilenamesReader &) = delete;
 
-  Error read(CovMapVersion Version,
-             BinaryCoverageReader::DecompressedData &Decompressed);
+  Error read(CovMapVersion Version);
 };
 
 } // end namespace coverage
Index: clang/test/Profile/profile-prefix-map.c
===================================================================
--- clang/test/Profile/profile-prefix-map.c
+++ clang/test/Profile/profile-prefix-map.c
@@ -5,10 +5,14 @@
 // RUN: echo "void f1() {}" > %t/root/nested/profile-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 profile-prefix-map.c nested/profile-prefix-map.c -o - | FileCheck --check-prefix=ABSOLUTE %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c %t/root/nested/profile-prefix-map.c -o - | FileCheck --check-prefix=ABSOLUTE %s
 //
-// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\01.*root.*nested.*profile-prefix-map\.c}}
+// ABSOLUTE: @__llvm_coverage_mapping = {{.*"\\02.*root.*nested.*profile-prefix-map\.c}}
 
-// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c nested/profile-prefix-map.c -fprofile-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=PROFILE-PREFIX-MAP %s --implicit-check-not=root
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c ../root/nested/profile-prefix-map.c -o - | FileCheck --check-prefix=RELATIVE %s
 //
+// RELATIVE: @__llvm_coverage_mapping = {{.*"\\02[^/]*}}..{{/|\\+}}root{{/|\\+}}nested{{.*profile-prefix-map\.c}}
+
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c %t/root/nested/profile-prefix-map.c -fprofile-prefix-map=%/t/root=. -o - | FileCheck --check-prefix=PROFILE-PREFIX-MAP %s
+// RUN: %clang_cc1 -fprofile-instrument=clang -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false -main-file-name profile-prefix-map.c ../root/nested/profile-prefix-map.c -fprofile-prefix-map=../root=. -o - | FileCheck --check-prefix=PROFILE-PREFIX-MAP %s
 // PROFILE-PREFIX-MAP: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\+}}nested{{.*profile-prefix-map\.c}}
Index: clang/test/CoverageMapping/abspath.cpp
===================================================================
--- clang/test/CoverageMapping/abspath.cpp
+++ clang/test/CoverageMapping/abspath.cpp
@@ -6,10 +6,14 @@
 
 // RUN: mkdir -p %t/test && cd %t/test
 // RUN: echo "void f1() {}" > f1.c
-// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -mllvm -enable-name-compression=false -emit-llvm -main-file-name abspath.cpp ../test/f1.c -o - | FileCheck -check-prefix=RELPATH %s
+// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -mllvm -enable-name-compression=false -emit-llvm -main-file-name abspath.cpp %t/test/f1.c -o - | FileCheck -check-prefix=ABSPATH %s
 
-// RELPATH: @__llvm_coverage_mapping = {{.*}}"\01
-// RELPATH: {{[/\\].*(/|\\\\)test(/|\\\\)f1}}.c
+// RELPATH: @__llvm_coverage_mapping = {{.*}}"\02
+// RELPATH: {{..(/|\\\\)test(/|\\\\)f1}}.c
 // RELPATH: "
 
+// ABSPATH: @__llvm_coverage_mapping = {{.*}}"\02
+// ABSPATH: {{[/\\].*(/|\\\\)test(/|\\\\)f1}}.c
+// ABSPATH: "
+
 void f1() {}
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -614,6 +614,19 @@
   return CodeGenOptions::FramePointerKind::None;
 }
 
+/// Add a CC1 option to specify the coverage compilation directory.
+static void addCoverageCompDirArg(const ArgList &Args, ArgStringList &CmdArgs,
+                                  const llvm::vfs::FileSystem &VFS) {
+  if (Arg *A = Args.getLastArg(options::OPT_fcoverage_compilation_dir)) {
+    CmdArgs.push_back("-fcoverage-compilation-dir");
+    CmdArgs.push_back(A->getValue());
+  } else if (llvm::ErrorOr<std::string> CWD =
+                 VFS.getCurrentWorkingDirectory()) {
+    CmdArgs.push_back("-fcoverage-compilation-dir");
+    CmdArgs.push_back(Args.MakeArgString(*CWD));
+  }
+}
+
 /// Add a CC1 option to specify the debug compilation directory.
 static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs,
                                const llvm::vfs::FileSystem &VFS) {
@@ -5285,6 +5298,10 @@
   if (!ShouldEnableAutolink(Args, TC, JA))
     CmdArgs.push_back("-fno-autolink");
 
+  // Add in -fcoverage-compilation-dir if necessary.
+  if (!Triple.isNVPTX() && !Triple.isAMDGCN())
+    addCoverageCompDirArg(Args, CmdArgs, D.getVFS());
+
   // Add in -fdebug-compilation-dir if necessary.
   addDebugCompDirArg(Args, CmdArgs, D.getVFS());
 
Index: clang/lib/CodeGen/CoverageMappingGen.h
===================================================================
--- clang/lib/CodeGen/CoverageMappingGen.h
+++ clang/lib/CodeGen/CoverageMappingGen.h
@@ -95,6 +95,7 @@
   std::vector<FunctionInfo> FunctionRecords;
   std::map<std::string, std::string> ProfilePrefixMap;
 
+  std::string getCurrentDirname();
   std::string normalizeFilename(StringRef Filename);
 
   /// Emit a function record.
Index: clang/lib/CodeGen/CoverageMappingGen.cpp
===================================================================
--- clang/lib/CodeGen/CoverageMappingGen.cpp
+++ clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1591,9 +1591,17 @@
   ProfilePrefixMap = CGM.getCodeGenOpts().ProfilePrefixMap;
 }
 
+std::string CoverageMappingModuleGen::getCurrentDirname() {
+  if (!CGM.getCodeGenOpts().CoverageCompilationDir.empty())
+    return CGM.getCodeGenOpts().CoverageCompilationDir;
+
+  SmallString<256> CWD;
+  llvm::sys::fs::current_path(CWD);
+  return CWD.str().str();
+}
+
 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 : ProfilePrefixMap) {
     if (llvm::sys::path::replace_path_prefix(Path, Entry.first, Entry.second))
@@ -1677,15 +1685,14 @@
     std::vector<StringRef> Filenames;
     std::vector<CounterExpression> Expressions;
     std::vector<CounterMappingRegion> Regions;
-    llvm::SmallVector<std::string, 16> FilenameStrs;
-    llvm::SmallVector<StringRef, 16> FilenameRefs;
-    FilenameStrs.resize(FileEntries.size());
-    FilenameRefs.resize(FileEntries.size());
+    std::vector<std::string> FilenameStrs;
+    FilenameStrs.resize(FileEntries.size() + 1);
+    FilenameStrs[0] = getCurrentDirname();
     for (const auto &Entry : FileEntries) {
       auto I = Entry.second;
       FilenameStrs[I] = normalizeFilename(Entry.first->getName());
-      FilenameRefs[I] = FilenameStrs[I];
     }
+    ArrayRef<std::string> FilenameRefs = llvm::makeArrayRef(FilenameStrs);
     RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames,
                                     Expressions, Regions);
     if (Reader.read())
@@ -1703,8 +1710,11 @@
   // 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());
+  FilenameStrs.resize(FileEntries.size() + 1);
+  FilenameRefs.resize(FileEntries.size() + 1);
+  // The first filename is the current working directory.
+  FilenameStrs[0] = getCurrentDirname();
+  FilenameRefs[0] = FilenameStrs[0];
   for (const auto &Entry : FileEntries) {
     auto I = Entry.second;
     FilenameStrs[I] = normalizeFilename(Entry.first->getName());
@@ -1772,7 +1782,7 @@
   auto It = FileEntries.find(File);
   if (It != FileEntries.end())
     return It->second;
-  unsigned FileID = FileEntries.size();
+  unsigned FileID = FileEntries.size() + 1;
   FileEntries.insert(std::make_pair(File, FileID));
   return FileID;
 }
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1104,6 +1104,13 @@
   CodeGenOpts<"CoverageMapping">, DefaultFalse,
   PosFlag<SetTrue, [CC1Option], "Generate coverage mapping to enable code coverage analysis">,
   NegFlag<SetFalse, [], "Disable code coverage analysis">, BothFlags<[CoreOption]>>;
+def fcoverage_compilation_dir : Separate<["-"], "fcoverage-compilation-dir">,
+    Group<f_Group>, Flags<[CC1Option, CC1AsOption, CoreOption]>,
+    HelpText<"The compilation directory to embed in the coverage mapping.">,
+    MarshallingInfoString<CodeGenOpts<"CoverageCompilationDir">>;
+def fcoverage_compilation_dir_EQ : Joined<["-"], "fcoverage-compilation-dir=">,
+    Group<f_Group>, Flags<[CC1Option, CC1AsOption, CoreOption]>,
+    Alias<fcoverage_compilation_dir>;
 def fprofile_generate : Flag<["-"], "fprofile-generate">,
     Group<f_Group>, Flags<[CoreOption]>,
     HelpText<"Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM_PROFILE_FILE env var)">;
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -160,6 +160,9 @@
   /// The version string to put into coverage files.
   char CoverageVersion[4];
 
+  /// The string to embed in coverage mapping as the current working directory.
+  std::string CoverageCompilationDir;
+
   /// Enable additional debugging information.
   std::string DebugPass;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to