From a9d784666ec1849ac4730254f1308524f9dfa744 Mon Sep 17 00:00:00 2001 From: Xinliang David Li Date: Wed, 13 Jan 2016 23:29:33 +0000 Subject: [Coverage] introduce class hierarchy (funcRecordReader) to support multiple versions of coverage data [resubmit after fixing build bot failures: qualify make_unique and eliminate -Wcovered-switch-default warning. With the planned size reduction change, the coverage format version is expected to be bumped up. This patch adds necessary support such that backward compatibility can be kept with maximal code sharing. Reading different versions of coverage data just requires instantiating the reader according to the version. No functional change is intended. Differiential Revision: http://reviews.llvm.org/D16133 llvm-svn: 257708 --- llvm/lib/ProfileData/CoverageMappingReader.cpp | 104 +++++++++++++++++++------ 1 file changed, 82 insertions(+), 22 deletions(-) (limited to 'llvm/lib/ProfileData/CoverageMappingReader.cpp') diff --git a/llvm/lib/ProfileData/CoverageMappingReader.cpp b/llvm/lib/ProfileData/CoverageMappingReader.cpp index 89e1cf42c57..d251e8dcb81 100644 --- a/llvm/lib/ProfileData/CoverageMappingReader.cpp +++ b/llvm/lib/ProfileData/CoverageMappingReader.cpp @@ -306,31 +306,57 @@ StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) { return Data.substr(Pointer - Address, Size); } -template -static std::error_code readCoverageMappingData( - InstrProfSymtab &ProfileNames, StringRef Data, - std::vector &Records, - std::vector &Filenames) { - using namespace support; - llvm::DenseSet UniqueFunctionMappingData; - - // Read the records in the coverage data section. - for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { +struct CovMapFuncRecordReader { + // The interface to read coverage mapping function records for + // a module. \p Buf is a reference to the buffer pointer pointing + // to the \c CovHeader of coverage mapping data associated with + // the module. + virtual std::error_code readFunctionRecords(const char *&Buf, + const char *End) = 0; + template + static std::unique_ptr + get(coverage::CoverageMappingVersion Version, InstrProfSymtab &P, + std::vector &R, + std::vector &F); +}; + +// A class for reading coverage mapping function records for a module. +template +class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader { + typedef typename coverage::CovMapTraits< + CovMapVersion, IntPtrT>::CovMapFuncRecordType FuncRecordType; + typedef typename coverage::CovMapTraits::NameRefType + NameRefType; + + llvm::DenseSet UniqueFunctionMappingData; + InstrProfSymtab &ProfileNames; + std::vector &Filenames; + std::vector &Records; + +public: + VersionedCovMapFuncRecordReader( + InstrProfSymtab &P, + std::vector &R, + std::vector &F) + : ProfileNames(P), Filenames(F), Records(R) {} + + std::error_code readFunctionRecords(const char *&Buf, + const char *End) override { + using namespace support; if (Buf + sizeof(CovMapHeader) > End) return coveragemap_error::malformed; auto CovHeader = reinterpret_cast(Buf); uint32_t NRecords = CovHeader->getNRecords(); uint32_t FilenamesSize = CovHeader->getFilenamesSize(); uint32_t CoverageSize = CovHeader->getCoverageSize(); - uint32_t Version = CovHeader->getVersion(); - Buf = reinterpret_cast(++CovHeader); - - if (Version > coverage::CoverageMappingCurrentVersion) - return coveragemap_error::unsupported_version; + assert((CoverageMappingVersion)CovHeader->getVersion() == + CovMapVersion); + Buf = reinterpret_cast(CovHeader + 1); // Skip past the function records, saving the start and end for later. const char *FunBuf = Buf; - Buf += NRecords * sizeof(coverage::CovMapFunctionRecord); + Buf += NRecords * sizeof(FuncRecordType); const char *FunEnd = Buf; // Get the filenames. @@ -353,8 +379,7 @@ static std::error_code readCoverageMappingData( // before reading the next map. Buf += alignmentAdjustment(Buf, 8); - auto CFR = - reinterpret_cast *>(FunBuf); + auto CFR = reinterpret_cast(FunBuf); while ((const char *)CFR < FunEnd) { // Read the function information uint32_t DataSize = CFR->template getDataSize(); @@ -369,7 +394,7 @@ static std::error_code readCoverageMappingData( // Ignore this record if we already have a record that points to the same // function name. This is useful to ignore the redundant records for the // functions with ODR linkage. - T NameRef = CFR->template getFuncNameRef(); + NameRefType NameRef = CFR->template getFuncNameRef(); if (!UniqueFunctionMappingData.insert(NameRef).second) continue; @@ -378,15 +403,50 @@ static std::error_code readCoverageMappingData( CFR->template getFuncName(ProfileNames, FuncName)) return EC; Records.push_back(BinaryCoverageReader::ProfileMappingRecord( - CoverageMappingVersion(Version), FuncName, FuncHash, Mapping, - FilenamesBegin, Filenames.size() - FilenamesBegin)); + CovMapVersion, FuncName, FuncHash, Mapping, FilenamesBegin, + Filenames.size() - FilenamesBegin)); CFR++; } + return std::error_code(); + } +}; + +template +std::unique_ptr CovMapFuncRecordReader::get( + coverage::CoverageMappingVersion Version, InstrProfSymtab &P, + std::vector &R, + std::vector &F) { + using namespace coverage; + switch (Version) { + case CoverageMappingVersion1: + return llvm::make_unique>(P, R, F); } + llvm_unreachable("Unsupported version"); +} +template +static std::error_code readCoverageMappingData( + InstrProfSymtab &ProfileNames, StringRef Data, + std::vector &Records, + std::vector &Filenames) { + using namespace coverage; + // Read the records in the coverage data section. + auto CovHeader = + reinterpret_cast(Data.data()); + CoverageMappingVersion Version = + (CoverageMappingVersion)CovHeader->getVersion(); + if (Version > coverage::CoverageMappingCurrentVersion) + return coveragemap_error::unsupported_version; + std::unique_ptr Reader = + CovMapFuncRecordReader::get(Version, ProfileNames, Records, + Filenames); + for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { + if (std::error_code EC = Reader->readFunctionRecords(Buf, End)) + return EC; + } return std::error_code(); } - static const char *TestingFormatMagic = "llvmcovmtestdata"; static std::error_code loadTestingFormat(StringRef Data, -- cgit v1.2.3