mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[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 llvm-svn: 257699
This commit is contained in:
parent
7f81c885ac
commit
7fc1d7a43d
@ -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
|
||||
|
@ -306,31 +306,57 @@ StringRef InstrProfSymtab::getFuncName(uint64_t Pointer, size_t Size) {
|
||||
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;
|
||||
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);
|
||||
};
|
||||
|
||||
// Read the records in the coverage data section.
|
||||
for (const char *Buf = Data.data(), *End = Buf + Data.size(); Buf < End;) {
|
||||
// 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 readCoverageMappingData(
|
||||
// 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 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<Endian>();
|
||||
NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
|
||||
if (!UniqueFunctionMappingData.insert(NameRef).second)
|
||||
continue;
|
||||
|
||||
@ -378,15 +403,53 @@ static std::error_code readCoverageMappingData(
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user