Index: include/llvm/ProfileData/CoverageMapping.h =================================================================== --- include/llvm/ProfileData/CoverageMapping.h +++ include/llvm/ProfileData/CoverageMapping.h @@ -543,6 +543,11 @@ CoverageMappingCurrentVersion = INSTR_PROF_COVMAP_VERSION }; +template struct CovMapTraits { + typedef CovMapFunctionRecord CovMapFuncRecordType; + typedef IntPtrT NameRefType; +}; + } // end namespace coverage /// \brief Provide DenseMapInfo for CounterExpression Index: lib/ProfileData/CoverageMappingReader.cpp =================================================================== --- lib/ProfileData/CoverageMappingReader.cpp +++ lib/ProfileData/CoverageMappingReader.cpp @@ -306,31 +306,50 @@ 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 { + 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); +}; + +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; + 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 +372,7 @@ // 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 +387,7 @@ // 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 +396,53 @@ 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(); } +}; - 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 make_unique>(P, R, + F); + default: + break; + } + 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. + std::unique_ptr Reader(nullptr); + for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) { + auto CovHeader = reinterpret_cast(Buf); + CoverageMappingVersion Version = + (CoverageMappingVersion)CovHeader->getVersion(); + if (Version > coverage::CoverageMappingCurrentVersion) + return coveragemap_error::unsupported_version; + if (!Reader) + Reader = CovMapFuncRecordReader::get(Version, ProfileNames, + Records, Filenames); + 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,