diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -172,6 +172,9 @@ /// The string to embed in debug information as the current working directory. std::string DebugCompilationDir; + /// The string to embed in coverage mapping as the current working directory. + std::string ProfileCompilationDir; + /// The string to embed in the debug information for the compile unit, if /// non-empty. std::string DwarfDebugFlags; diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1103,6 +1103,10 @@ def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, Group, Flags<[CC1Option, CC1AsOption, CoreOption]>, Alias; +def fprofile_compilation_dir_EQ : Joined<["-"], "fprofile-compilation-dir=">, + Group, Flags<[CC1Option, CC1AsOption, CoreOption]>, + HelpText<"The compilation directory to embed in the coverage mapping.">, + MarshallingInfoString>; defm debug_info_for_profiling : BoolFOption<"debug-info-for-profiling", CodeGenOpts<"DebugInfoForProfiling">, DefaultFalse, PosFlag, diff --git a/clang/lib/CodeGen/CoverageMappingGen.h b/clang/lib/CodeGen/CoverageMappingGen.h --- a/clang/lib/CodeGen/CoverageMappingGen.h +++ b/clang/lib/CodeGen/CoverageMappingGen.h @@ -95,6 +95,7 @@ std::vector FunctionRecords; std::map ProfilePrefixMap; + std::string getCurrentDirname(); std::string normalizeFilename(StringRef Filename); /// Emit a function record. diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp --- a/clang/lib/CodeGen/CoverageMappingGen.cpp +++ b/clang/lib/CodeGen/CoverageMappingGen.cpp @@ -1606,9 +1606,17 @@ ProfilePrefixMap = CGM.getCodeGenOpts().ProfilePrefixMap; } +std::string CoverageMappingModuleGen::getCurrentDirname() { + if (!CGM.getCodeGenOpts().ProfileCompilationDir.empty()) + return CGM.getCodeGenOpts().ProfileCompilationDir; + + 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)) @@ -1689,18 +1697,17 @@ // also processed by the CoverageMappingWriter which performs // additional minimization operations such as reducing the number of // expressions. + llvm::SmallVector FilenameStrs; std::vector Filenames; std::vector Expressions; std::vector Regions; - llvm::SmallVector FilenameStrs; - llvm::SmallVector FilenameRefs; - FilenameStrs.resize(FileEntries.size()); - FilenameRefs.resize(FileEntries.size()); + FilenameStrs.resize(FileEntries.size() + 1); + FilenameStrs[0] = normalizeFilename(getCurrentDirname()); for (const auto &Entry : FileEntries) { auto I = Entry.second; FilenameStrs[I] = normalizeFilename(Entry.first->getName()); - FilenameRefs[I] = FilenameStrs[I]; } + ArrayRef FilenameRefs = llvm::makeArrayRef(FilenameStrs); RawCoverageMappingReader Reader(CoverageMapping, FilenameRefs, Filenames, Expressions, Regions); if (Reader.read()) @@ -1717,19 +1724,18 @@ // Create the filenames and merge them with coverage mappings llvm::SmallVector FilenameStrs; - llvm::SmallVector FilenameRefs; - FilenameStrs.resize(FileEntries.size()); - FilenameRefs.resize(FileEntries.size()); + FilenameStrs.resize(FileEntries.size() + 1); + // The first filename is the current working directory. + FilenameStrs[0] = getCurrentDirname(); for (const auto &Entry : FileEntries) { auto I = Entry.second; FilenameStrs[I] = normalizeFilename(Entry.first->getName()); - FilenameRefs[I] = FilenameStrs[I]; } std::string Filenames; { llvm::raw_string_ostream OS(Filenames); - CoverageFilenamesSectionWriter(FilenameRefs).write(OS); + CoverageFilenamesSectionWriter(FilenameStrs).write(OS); } auto *FilenamesVal = llvm::ConstantDataArray::getString(Ctx, Filenames, false); @@ -1787,7 +1793,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; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -858,6 +858,13 @@ CmdArgs.push_back("-fcoverage-mapping"); } + if (Arg *A = Args.getLastArg(options::OPT_fprofile_compilation_dir_EQ)) { + A->render(Args, CmdArgs); + } else if (llvm::ErrorOr CWD = + D.getVFS().getCurrentWorkingDirectory()) { + Args.MakeArgString("-fprofile-compilation-dir=" + *CWD); + } + if (Args.hasArg(options::OPT_fprofile_exclude_files_EQ)) { auto *Arg = Args.getLastArg(options::OPT_fprofile_exclude_files_EQ); if (!Args.hasArg(options::OPT_coverage)) diff --git a/clang/test/CodeGen/profile-compilation-dir.c b/clang/test/CodeGen/profile-compilation-dir.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/profile-compilation-dir.c @@ -0,0 +1,7 @@ +// RUN: mkdir -p %t.dir && cd %t.dir +// RUN: cp %s rel.c +// RUN: %clang_cc1 -fprofile-instrument=clang -fprofile-compilation-dir=/nonsense -fcoverage-mapping -emit-llvm -mllvm -enable-name-compression=false rel.c -o - | FileCheck -check-prefix=CHECK-NONSENSE %s + +// CHECK-NONSENSE: nonsense + +void f() {} diff --git a/clang/test/CoverageMapping/abspath.cpp b/clang/test/CoverageMapping/abspath.cpp --- a/clang/test/CoverageMapping/abspath.cpp +++ b/clang/test/CoverageMapping/abspath.cpp @@ -1,15 +1,19 @@ // 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 %S/Inputs/../abspath.cpp -o - | FileCheck -check-prefix=RMDOTS %s -// RMDOTS: @__llvm_coverage_mapping = {{.*}}"\01 +// RMDOTS: @__llvm_coverage_mapping = {{.*}}"\02 // RMDOTS-NOT: Inputs // RMDOTS: " // 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() {} diff --git a/clang/test/Profile/profile-prefix-map.c b/clang/test/Profile/profile-prefix-map.c --- a/clang/test/Profile/profile-prefix-map.c +++ b/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 // -// PROFILE-PREFIX-MAP: @__llvm_coverage_mapping = {{.*"\\01[^/]*}}.{{/|\\+}}nested{{.*profile-prefix-map\.c}} +// 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 = {{.*"\\02.*}}.{{/|\\+}}nested{{.*profile-prefix-map\.c}} diff --git a/compiler-rt/include/profile/InstrProfData.inc b/compiler-rt/include/profile/InstrProfData.inc --- a/compiler-rt/include/profile/InstrProfData.inc +++ b/compiler-rt/include/profile/InstrProfData.inc @@ -649,7 +649,7 @@ /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 7 /* Coverage mapping format version (start from 0). */ -#define INSTR_PROF_COVMAP_VERSION 4 +#define INSTR_PROF_COVMAP_VERSION 5 /* Profile version is always of type uint64_t. Reserve the upper 8 bits in the * version for other variants of profile. We set the lowest bit of the upper 8 diff --git a/llvm/docs/CoverageMappingFormat.rst b/llvm/docs/CoverageMappingFormat.rst --- a/llvm/docs/CoverageMappingFormat.rst +++ b/llvm/docs/CoverageMappingFormat.rst @@ -266,7 +266,16 @@ [32 x i8] c"..." ; Encoded data (dissected later) }, section "__llvm_covmap", align 8 -The current version of the format is version 5. There is one difference from version 4: +The current version of the format is version 6. + +There is one difference between versions 6 and 5: + +* The first entry in the filename list is the compilation directory. When the + filename is relative, the compilation directory is combined with the relative + path to get an absolute path. This can reduce size by omitting the duplicate + prefix in filenames. + +There is one difference between versions 5 and 4: * The notion of branch region has been introduced along with a corresponding region kind. Branch regions encode two counters, one to track how many diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h @@ -996,7 +996,10 @@ Version4 = 3, // Branch regions referring to two counters are added Version5 = 4, - // The current version is Version5. + // Compilation directory is stored separately and combined with relative + // filenames to produce an absolute file path. + Version6 = 5, + // The current version is Version6. CurrentVersion = INSTR_PROF_COVMAP_VERSION }; diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h @@ -125,14 +125,14 @@ /// Reader for the raw coverage mapping data. class RawCoverageMappingReader : public RawCoverageReader { - ArrayRef TranslationUnitFilenames; + ArrayRef &TranslationUnitFilenames; std::vector &Filenames; std::vector &Expressions; std::vector &MappingRegions; public: RawCoverageMappingReader(StringRef MappingData, - ArrayRef TranslationUnitFilenames, + ArrayRef &TranslationUnitFilenames, std::vector &Filenames, std::vector &Expressions, std::vector &MappingRegions) @@ -174,10 +174,8 @@ FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {} }; - using DecompressedData = std::vector>>; - private: - std::vector Filenames; + std::vector Filenames; std::vector 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 &Filenames; + std::vector &Filenames; // Read an uncompressed sequence of filenames. - Error readUncompressed(uint64_t NumFilenames); + Error readUncompressed(CovMapVersion Version, uint64_t NumFilenames); public: - RawCoverageFilenamesReader(StringRef Data, std::vector &Filenames) + RawCoverageFilenamesReader(StringRef Data, + std::vector &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 diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h --- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h +++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingWriter.h @@ -27,10 +27,10 @@ /// Writer of the filenames section for the instrumentation /// based code coverage. class CoverageFilenamesSectionWriter { - ArrayRef Filenames; + ArrayRef Filenames; public: - CoverageFilenamesSectionWriter(ArrayRef Filenames); + CoverageFilenamesSectionWriter(ArrayRef Filenames); /// Write encoded filenames to the given output stream. If \p Compress is /// true, attempt to compress the filenames. diff --git a/llvm/include/llvm/ProfileData/InstrProfData.inc b/llvm/include/llvm/ProfileData/InstrProfData.inc --- a/llvm/include/llvm/ProfileData/InstrProfData.inc +++ b/llvm/include/llvm/ProfileData/InstrProfData.inc @@ -649,7 +649,7 @@ /* Indexed profile format version (start from 1). */ #define INSTR_PROF_INDEX_VERSION 7 /* Coverage mapping format version (start from 0). */ -#define INSTR_PROF_COVMAP_VERSION 4 +#define INSTR_PROF_COVMAP_VERSION 5 /* Profile version is always of type uint64_t. Reserve the upper 8 bits in the * version for other variants of profile. We set the lowest bit of the upper 8 diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/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; @@ -107,7 +105,7 @@ return make_error(coveragemap_error::malformed); if (Version < CovMapVersion::Version4) - return readUncompressed(NumFilenames); + return readUncompressed(Version, NumFilenames); // The uncompressed length may exceed the size of the encoded filenames. // Skip size validation. @@ -124,11 +122,8 @@ return make_error( coveragemap_error::decompression_failed); - // Allocate memory for the decompressed filenames. Transfer ownership of - // the memory to BinaryCoverageReader. - auto DecompressedStorage = std::make_unique>(); - SmallVectorImpl &StorageBuf = *DecompressedStorage.get(); - Decompressed.push_back(std::move(DecompressedStorage)); + // Allocate memory for the decompressed filenames. + SmallVector StorageBuf; // Read compressed filenames. StringRef CompressedFilenames = Data.substr(0, CompressedLen); @@ -143,19 +138,40 @@ StringRef UncompressedFilenames(StorageBuf.data(), StorageBuf.size()); RawCoverageFilenamesReader Delegate(UncompressedFilenames, Filenames); - return Delegate.readUncompressed(NumFilenames); + return Delegate.readUncompressed(Version, NumFilenames); } - return readUncompressed(NumFilenames); + return readUncompressed(Version, NumFilenames); } -Error RawCoverageFilenamesReader::readUncompressed(uint64_t NumFilenames) { +Error RawCoverageFilenamesReader::readUncompressed(CovMapVersion Version, + uint64_t NumFilenames) { // Read uncompressed filenames. - for (size_t I = 0; I < NumFilenames; ++I) { - StringRef Filename; - if (auto Err = readString(Filename)) + if (Version < CovMapVersion::Version6) { + for (size_t I = 0; I < NumFilenames; ++I) { + StringRef Filename; + if (auto Err = readString(Filename)) + return Err; + Filenames.push_back(Filename.str()); + } + } else { + StringRef CWD; + if (auto Err = readString(CWD)) return Err; - Filenames.push_back(Filename); + Filenames.push_back(CWD.str()); + + for (size_t I = 1; I < NumFilenames; ++I) { + StringRef Filename; + if (auto Err = readString(Filename)) + return Err; + 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(P)); + } + } } return Error::success(); } @@ -481,9 +497,8 @@ // // Returns a pointer to the next \c CovHeader if it exists, or to an address // greater than \p CovEnd if not. - virtual Expected - readCoverageHeader(const char *CovBuf, const char *CovBufEnd, - BinaryCoverageReader::DecompressedData &Decompressed) = 0; + virtual Expected readCoverageHeader(const char *CovBuf, + const char *CovBufEnd) = 0; // Read function records. // @@ -505,7 +520,7 @@ static Expected> get(CovMapVersion Version, InstrProfSymtab &P, std::vector &R, - std::vector &F); + std::vector &F); }; // A class for reading coverage mapping function records for a module. @@ -519,7 +534,7 @@ // in \c Records. DenseMap FunctionRecords; InstrProfSymtab &ProfileNames; - std::vector &Filenames; + std::vector &Filenames; std::vector &Records; // Maps a hash of the filenames in a TU to a \c FileRange. The range @@ -579,14 +594,13 @@ VersionedCovMapFuncRecordReader( InstrProfSymtab &P, std::vector &R, - std::vector &F) + std::vector &F) : ProfileNames(P), Filenames(F), Records(R) {} ~VersionedCovMapFuncRecordReader() override = default; - Expected readCoverageHeader( - const char *CovBuf, const char *CovBufEnd, - BinaryCoverageReader::DecompressedData &Decompressed) override { + Expected readCoverageHeader(const char *CovBuf, + const char *CovBufEnd) override { using namespace support; if (CovBuf + sizeof(CovMapHeader) > CovBufEnd) @@ -615,7 +629,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 +735,7 @@ Expected> CovMapFuncRecordReader::get( CovMapVersion Version, InstrProfSymtab &P, std::vector &R, - std::vector &F) { + std::vector &F) { using namespace coverage; switch (Version) { @@ -732,6 +746,7 @@ case CovMapVersion::Version3: case CovMapVersion::Version4: case CovMapVersion::Version5: + case CovMapVersion::Version6: // Decompress the name data. if (Error E = P.create(P.getNameData())) return std::move(E); @@ -747,6 +762,9 @@ else if (Version == CovMapVersion::Version5) return std::make_unique>(P, R, F); + else if (Version == CovMapVersion::Version6) + return std::make_unique>(P, R, F); } llvm_unreachable("Unsupported version"); } @@ -755,8 +773,7 @@ static Error readCoverageMappingData( InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords, std::vector &Records, - std::vector &Filenames, - BinaryCoverageReader::DecompressedData &Decompressed) { + std::vector &Filenames) { using namespace coverage; // Read the records in the coverage data section. @@ -782,8 +799,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 +826,23 @@ if (Error E = readCoverageMappingData( 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( 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( 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( Reader->ProfileNames, Coverage, FuncRecordsRef, - Reader->MappingRecords, Reader->Filenames, Reader->Decompressed)) + Reader->MappingRecords, Reader->Filenames)) return std::move(E); } else return make_error(coveragemap_error::malformed); @@ -1075,10 +1089,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; diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp --- a/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp @@ -27,7 +27,7 @@ using namespace coverage; CoverageFilenamesSectionWriter::CoverageFilenamesSectionWriter( - ArrayRef Filenames) + ArrayRef Filenames) : Filenames(Filenames) { #ifndef NDEBUG StringSet<> NameSet; diff --git a/llvm/test/tools/llvm-cov/Inputs/binary-formats.v6.linux64l b/llvm/test/tools/llvm-cov/Inputs/binary-formats.v6.linux64l new file mode 100755 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@> { bool UseMultipleReaders; StringMap Files; + std::vector Filenames; std::vector InputFunctions; std::vector OutputFunctions; @@ -146,7 +147,7 @@ auto R = Files.find(Name); if (R != Files.end()) return R->second; - unsigned Index = Files.size(); + unsigned Index = Files.size() + 1; Files.try_emplace(Name, Index); return Index; } @@ -200,11 +201,12 @@ void readCoverageRegions(const std::string &Coverage, OutputFunctionCoverageData &Data) { - SmallVector Filenames(Files.size()); + Filenames.resize(Files.size() + 1); for (const auto &E : Files) - Filenames[E.getValue()] = E.getKey(); + Filenames[E.getValue()] = E.getKey().str(); std::vector Expressions; - RawCoverageMappingReader Reader(Coverage, Filenames, Data.Filenames, + ArrayRef FilenameRefs = llvm::makeArrayRef(Filenames); + RawCoverageMappingReader Reader(Coverage, FilenameRefs, Data.Filenames, Expressions, Data.Regions); EXPECT_THAT_ERROR(Reader.read(), Succeeded()); } @@ -895,7 +897,7 @@ std::pair({true, true})),); TEST(CoverageMappingTest, filename_roundtrip) { - std::vector Paths({"a", "b", "c", "d", "e"}); + std::vector Paths({"", "a", "b", "c", "d", "e"}); for (bool Compress : {false, true}) { std::string EncodedFilenames; @@ -905,16 +907,12 @@ Writer.write(OS, Compress); } - std::vector ReadFilenames; + std::vector ReadFilenames; RawCoverageFilenamesReader Reader(EncodedFilenames, ReadFilenames); - BinaryCoverageReader::DecompressedData Decompressed; - EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion, Decompressed), - Succeeded()); - if (!Compress) - ASSERT_EQ(Decompressed.size(), 0U); + EXPECT_THAT_ERROR(Reader.read(CovMapVersion::CurrentVersion), Succeeded()); ASSERT_EQ(ReadFilenames.size(), Paths.size()); - for (unsigned I = 0; I < Paths.size(); ++I) + for (unsigned I = 1; I < Paths.size(); ++I) ASSERT_TRUE(ReadFilenames[I] == Paths[I]); } }