From 97ec8fa5bb07e3f5bf25ddcb216b545cd3d03b65 Mon Sep 17 00:00:00 2001 From: Petr Hosek Date: Wed, 10 Feb 2021 00:25:34 -0800 Subject: [Coverage] Store compilation dir separately in coverage mapping We currently always store absolute filenames in coverage mapping. This is problematic for several reasons. It poses a problem for distributed compilation as source location might vary across machines. We are also duplicating the path prefix potentially wasting space. This change modifies how we store filenames in coverage mapping. Rather than absolute paths, it stores the compilation directory and file paths as given to the compiler, either relative or absolute. Later when reading the coverage mapping information, we recombine relative paths with the working directory. This approach is similar to handling ofDW_AT_comp_dir in DWARF. Finally, we also provide a new option, -fprofile-compilation-dir akin to -fdebug-compilation-dir which can be used to manually override the compilation directory which is useful in distributed compilation cases. Differential Revision: https://reviews.llvm.org/D95753 --- .../ProfileData/Coverage/CoverageMappingReader.cpp | 95 ++++++++++++---------- 1 file changed, 54 insertions(+), 41 deletions(-) (limited to 'llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp') diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp index 1acdcb4..942f8e7 100644 --- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp @@ -97,9 +97,7 @@ Error RawCoverageReader::readString(StringRef &Result) { 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 @@ Error RawCoverageFilenamesReader::read( 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 @@ Error RawCoverageFilenamesReader::read( 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 @@ Error RawCoverageFilenamesReader::read( 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 @@ struct CovMapFuncRecordReader { // // 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 @@ struct CovMapFuncRecordReader { 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 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { // 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 @@ public: 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 @@ public: 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 @@ template 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 @@ Expected> CovMapFuncRecordReader::get( 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 @@ Expected> CovMapFuncRecordReader::get( 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 @@ template 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 @@ static Error readCoverageMappingData( // 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 @@ BinaryCoverageReader::createCoverageReaderFromBuffer( 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 @@ Error BinaryCoverageReader::readNextRecord(CoverageMappingRecord &Record) { 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; -- cgit v1.1