[llvm] r257699 - [Coverage] introduce class hierarchy (funcRecordReader) to support multiple versions of coverage data

Xinliang David Li via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 13 14:58:43 PST 2016


Author: davidxl
Date: Wed Jan 13 16:58:42 2016
New Revision: 257699

URL: http://llvm.org/viewvc/llvm-project?rev=257699&view=rev
Log:
[Coverage] introduce class hierarchy (funcRecordReader) to support multiple versions of coverage data

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

Modified:
    llvm/trunk/include/llvm/ProfileData/CoverageMapping.h
    llvm/trunk/lib/ProfileData/CoverageMappingReader.cpp

Modified: llvm/trunk/include/llvm/ProfileData/CoverageMapping.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/CoverageMapping.h?rev=257699&r1=257698&r2=257699&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/CoverageMapping.h (original)
+++ llvm/trunk/include/llvm/ProfileData/CoverageMapping.h Wed Jan 13 16:58:42 2016
@@ -543,6 +543,11 @@ enum CoverageMappingVersion {
   CoverageMappingCurrentVersion = INSTR_PROF_COVMAP_VERSION
 };
 
+template <int CovMapVersion, class IntPtrT> struct CovMapTraits {
+  typedef CovMapFunctionRecord<IntPtrT> CovMapFuncRecordType;
+  typedef IntPtrT NameRefType;
+};
+
 } // end namespace coverage
 
 /// \brief Provide DenseMapInfo for CounterExpression

Modified: llvm/trunk/lib/ProfileData/CoverageMappingReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/CoverageMappingReader.cpp?rev=257699&r1=257698&r2=257699&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/CoverageMappingReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/CoverageMappingReader.cpp Wed Jan 13 16:58:42 2016
@@ -306,31 +306,57 @@ StringRef InstrProfSymtab::getFuncName(u
   return Data.substr(Pointer - Address, Size);
 }
 
-template <typename T, support::endianness Endian>
-static std::error_code readCoverageMappingData(
-    InstrProfSymtab &ProfileNames, StringRef Data,
-    std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
-    std::vector<StringRef> &Filenames) {
-  using namespace support;
-  llvm::DenseSet<T> 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 <class IntPtrT, support::endianness Endian>
+  static std::unique_ptr<CovMapFuncRecordReader>
+  get(coverage::CoverageMappingVersion Version, InstrProfSymtab &P,
+      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
+      std::vector<StringRef> &F);
+};
+
+// A class for reading coverage mapping function records for a module.
+template <coverage::CoverageMappingVersion CovMapVersion, class IntPtrT,
+          support::endianness Endian>
+class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
+  typedef typename coverage::CovMapTraits<
+      CovMapVersion, IntPtrT>::CovMapFuncRecordType FuncRecordType;
+  typedef typename coverage::CovMapTraits<CovMapVersion, IntPtrT>::NameRefType
+      NameRefType;
+
+  llvm::DenseSet<NameRefType> UniqueFunctionMappingData;
+  InstrProfSymtab &ProfileNames;
+  std::vector<StringRef> &Filenames;
+  std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
+
+public:
+  VersionedCovMapFuncRecordReader(
+      InstrProfSymtab &P,
+      std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
+      std::vector<StringRef> &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<const coverage::CovMapHeader *>(Buf);
     uint32_t NRecords = CovHeader->getNRecords<Endian>();
     uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
     uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
-    uint32_t Version = CovHeader->getVersion<Endian>();
-    Buf = reinterpret_cast<const char *>(++CovHeader);
-
-    if (Version > coverage::CoverageMappingCurrentVersion)
-      return coveragemap_error::unsupported_version;
+    assert((CoverageMappingVersion)CovHeader->getVersion<Endian>() ==
+           CovMapVersion);
+    Buf = reinterpret_cast<const char *>(CovHeader + 1);
 
     // Skip past the function records, saving the start and end for later.
     const char *FunBuf = Buf;
-    Buf += NRecords * sizeof(coverage::CovMapFunctionRecord<T>);
+    Buf += NRecords * sizeof(FuncRecordType);
     const char *FunEnd = Buf;
 
     // Get the filenames.
@@ -353,8 +379,7 @@ static std::error_code readCoverageMappi
     // before reading the next map.
     Buf += alignmentAdjustment(Buf, 8);
 
-    auto CFR =
-        reinterpret_cast<const coverage::CovMapFunctionRecord<T> *>(FunBuf);
+    auto CFR = reinterpret_cast<const FuncRecordType *>(FunBuf);
     while ((const char *)CFR < FunEnd) {
       // Read the function information
       uint32_t DataSize = CFR->template getDataSize<Endian>();
@@ -369,7 +394,7 @@ static std::error_code readCoverageMappi
       // 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<Endian>();
+      NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
       if (!UniqueFunctionMappingData.insert(NameRef).second)
         continue;
 
@@ -378,15 +403,53 @@ static std::error_code readCoverageMappi
               CFR->template getFuncName<Endian>(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 <class IntPtrT, support::endianness Endian>
+std::unique_ptr<CovMapFuncRecordReader> CovMapFuncRecordReader::get(
+    coverage::CoverageMappingVersion Version, InstrProfSymtab &P,
+    std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
+    std::vector<StringRef> &F) {
+  using namespace coverage;
+  switch (Version) {
+  case CoverageMappingVersion1:
+    return make_unique<VersionedCovMapFuncRecordReader<CoverageMappingVersion1,
+                                                       IntPtrT, Endian>>(P, R,
+                                                                         F);
+  default:
+    break;
+  }
+  llvm_unreachable("Unsupported version");
 }
 
+template <typename T, support::endianness Endian>
+static std::error_code readCoverageMappingData(
+    InstrProfSymtab &ProfileNames, StringRef Data,
+    std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
+    std::vector<StringRef> &Filenames) {
+  using namespace coverage;
+  // Read the records in the coverage data section.
+  auto CovHeader =
+      reinterpret_cast<const coverage::CovMapHeader *>(Data.data());
+  CoverageMappingVersion Version =
+      (CoverageMappingVersion)CovHeader->getVersion<Endian>();
+  if (Version > coverage::CoverageMappingCurrentVersion)
+    return coveragemap_error::unsupported_version;
+  std::unique_ptr<CovMapFuncRecordReader> Reader =
+      CovMapFuncRecordReader::get<T, Endian>(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,




More information about the llvm-commits mailing list