38 using namespace coverage;
41 #define DEBUG_TYPE "coverage-mapping" 43 void CoverageMappingIterator::increment() {
49 if (
auto E = Reader->readNextRecord(
Record))
72 if (Result >= MaxPlus1)
81 if (Result >
Data.size())
88 if (
auto Err = readSize(Length))
90 Result =
Data.substr(0, Length);
96 uint64_t NumFilenames;
97 if (
auto Err = readSize(NumFilenames))
99 for (
size_t I = 0;
I < NumFilenames; ++
I) {
103 Filenames.push_back(Filename);
137 Error RawCoverageMappingReader::readCounter(
Counter &C) {
138 uint64_t EncodedCounter;
142 if (
auto Err = decodeCounter(EncodedCounter, C))
153 Error RawCoverageMappingReader::readMappingRegionsSubArray(
154 std::vector<CounterMappingRegion> &MappingRegions,
unsigned InferredFileID,
157 if (
auto Err = readSize(NumRegions))
159 unsigned LineStart = 0;
160 for (
size_t I = 0;
I < NumRegions; ++
I) {
165 uint64_t EncodedCounterAndRegion;
166 if (
auto Err = readIntMax(EncodedCounterAndRegion,
170 uint64_t ExpandedFileID = 0;
172 if (
auto Err = decodeCounter(EncodedCounterAndRegion, C))
176 if (EncodedCounterAndRegion & EncodingExpansionRegionBit) {
178 ExpandedFileID = EncodedCounterAndRegion >>
180 if (ExpandedFileID >= NumFileIDs)
183 switch (EncodedCounterAndRegion >>
198 uint64_t LineStartDelta, ColumnStart, NumLines, ColumnEnd;
210 LineStart += LineStartDelta;
213 if (ColumnEnd & (1U << 31)) {
215 ColumnEnd &= ~(1U << 31);
226 if (ColumnStart == 0 && ColumnEnd == 0) {
232 dbgs() <<
"Counter in file " << InferredFileID <<
" " << LineStart <<
":" 233 << ColumnStart <<
" -> " << (LineStart + NumLines) <<
":" 234 << ColumnEnd <<
", ";
236 dbgs() <<
"Expands to file " << ExpandedFileID;
243 LineStart, ColumnStart,
244 LineStart + NumLines, ColumnEnd, Kind);
245 if (CMR.startLoc() > CMR.endLoc())
247 MappingRegions.push_back(CMR);
255 uint64_t NumFileMappings;
256 if (
auto Err = readSize(NumFileMappings))
258 for (
size_t I = 0;
I < NumFileMappings; ++
I) {
259 uint64_t FilenameIndex;
260 if (
auto Err = readIntMax(FilenameIndex, TranslationUnitFilenames.size()))
262 VirtualFileMapping.
push_back(FilenameIndex);
266 for (
auto I : VirtualFileMapping) {
267 Filenames.push_back(TranslationUnitFilenames[
I]);
271 uint64_t NumExpressions;
272 if (
auto Err = readSize(NumExpressions))
280 for (
size_t I = 0;
I < NumExpressions; ++
I) {
288 for (
unsigned InferredFileID = 0, S = VirtualFileMapping.size();
289 InferredFileID < S; ++InferredFileID) {
290 if (
auto Err = readMappingRegionsSubArray(MappingRegions, InferredFileID,
291 VirtualFileMapping.size()))
301 FileIDExpansionRegionMapping.
resize(VirtualFileMapping.size(),
nullptr);
302 for (
unsigned Pass = 1, S = VirtualFileMapping.size();
Pass < S; ++
Pass) {
303 for (
auto &R : MappingRegions) {
306 assert(!FileIDExpansionRegionMapping[R.ExpandedFileID]);
307 FileIDExpansionRegionMapping[R.ExpandedFileID] = &R;
309 for (
auto &R : MappingRegions) {
310 if (FileIDExpansionRegionMapping[R.FileID]) {
311 FileIDExpansionRegionMapping[R.FileID]->Count = R.Count;
312 FileIDExpansionRegionMapping[R.FileID] =
nullptr;
322 uint64_t NumFileMappings;
323 if (
Error Err = readSize(NumFileMappings))
324 return std::move(Err);
325 if (NumFileMappings != 1)
328 uint64_t FilenameIndex;
331 return std::move(Err);
332 uint64_t NumExpressions;
333 if (
Error Err = readSize(NumExpressions))
334 return std::move(Err);
335 if (NumExpressions != 0)
338 if (
Error Err = readSize(NumRegions))
339 return std::move(Err);
342 uint64_t EncodedCounterAndRegion;
343 if (
Error Err = readIntMax(EncodedCounterAndRegion,
345 return std::move(Err);
351 if (
auto EC = Section.getContents(
Data))
353 Address = Section.getAddress();
363 return Data.substr(Pointer - Address, Size);
376 struct CovMapFuncRecordReader {
377 virtual ~CovMapFuncRecordReader() =
default;
387 const char *End) = 0;
389 template <
class IntPtrT, support::endianness Endian>
392 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
393 std::vector<StringRef> &
F);
397 template <CovMapVersion Version,
class IntPtrT, support::endianness Endian>
398 class VersionedCovMapFuncRecordReader :
public CovMapFuncRecordReader {
399 using FuncRecordType =
407 std::vector<StringRef> &Filenames;
408 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records;
416 Error insertFunctionRecordIfNeeded(
const FuncRecordType *CFR,
417 StringRef Mapping,
size_t FilenamesBegin) {
418 uint64_t FuncHash = CFR->template getFuncHash<Endian>();
419 NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
421 FunctionRecords.
insert(std::make_pair(NameRef, Records.size()));
422 if (InsertResult.second) {
424 if (
Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
426 if (FuncName.
empty())
428 Records.emplace_back(
Version, FuncName, FuncHash, Mapping, FilenamesBegin,
429 Filenames.
size() - FilenamesBegin);
433 size_t OldRecordIndex = InsertResult.first->second;
435 Records[OldRecordIndex];
440 if (!*OldIsDummyExpected)
446 if (*NewIsDummyExpected)
456 VersionedCovMapFuncRecordReader(
458 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
459 std::vector<StringRef> &
F)
460 : ProfileNames(P), Filenames(F), Records(R) {}
462 ~VersionedCovMapFuncRecordReader()
override =
default;
465 const char *End)
override {
466 using namespace support;
470 auto CovHeader =
reinterpret_cast<const CovMapHeader *
>(Buf);
471 uint32_t NRecords = CovHeader->getNRecords<Endian>();
472 uint32_t FilenamesSize = CovHeader->getFilenamesSize<Endian>();
473 uint32_t CoverageSize = CovHeader->getCoverageSize<Endian>();
475 Buf =
reinterpret_cast<const char *
>(CovHeader + 1);
478 const char *FunBuf = Buf;
479 Buf += NRecords *
sizeof(FuncRecordType);
480 const char *FunEnd = Buf;
483 if (Buf + FilenamesSize > End)
485 size_t FilenamesBegin = Filenames.size();
487 if (
auto Err = Reader.
read())
488 return std::move(Err);
489 Buf += FilenamesSize;
492 const char *CovBuf = Buf;
494 const char *CovEnd = Buf;
502 auto CFR =
reinterpret_cast<const FuncRecordType *
>(FunBuf);
503 while ((
const char *)CFR < FunEnd) {
505 uint32_t DataSize = CFR->template getDataSize<Endian>();
508 if (CovBuf + DataSize > CovEnd)
510 auto Mapping =
StringRef(CovBuf, DataSize);
514 insertFunctionRecordIfNeeded(CFR, Mapping, FilenamesBegin))
515 return std::move(Err);
524 template <
class IntPtrT, support::endianness Endian>
527 std::vector<BinaryCoverageReader::ProfileMappingRecord> &R,
528 std::vector<StringRef> &
F) {
529 using namespace coverage;
538 if (
Error E = P.create(P.getNameData()))
550 template <
typename T, support::endianness Endian>
553 std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
554 std::vector<StringRef> &Filenames) {
555 using namespace coverage;
564 CovMapFuncRecordReader::get<T, Endian>(
Version, ProfileNames, Records,
566 if (
Error E = ReaderExpected.takeError())
568 auto Reader = std::move(ReaderExpected.get());
569 for (
const char *Buf = Data.
data(), *End = Buf + Data.
size(); Buf < End;) {
570 auto NextHeaderOrErr = Reader->readFunctionRecords(Buf, End);
571 if (
auto E = NextHeaderOrErr.takeError())
573 Buf = NextHeaderOrErr.get();
582 uint8_t &BytesInAddress,
591 auto ProfileNamesSize =
604 if (Data.
size() < ProfileNamesSize)
608 CoverageMapping = Data.
substr(ProfileNamesSize);
610 if (CoverageMapping.
empty())
613 if (CoverageMapping.
size() < Pad)
615 CoverageMapping = CoverageMapping.
substr(Pad);
621 for (
const auto &
Section : OF.sections()) {
622 if (
auto EC =
Section.getName(FoundName))
624 if (FoundName == Name)
633 uint8_t &BytesInAddress,
637 return BinOrErr.takeError();
638 auto Bin = std::move(BinOrErr.get());
639 std::unique_ptr<ObjectFile> OF;
640 if (
auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
643 auto ObjectFileOrErr = Universal->getObjectForArch(Arch);
644 if (!ObjectFileOrErr)
645 return ObjectFileOrErr.takeError();
646 OF = std::move(ObjectFileOrErr.get());
647 }
else if (isa<ObjectFile>(Bin.get())) {
649 OF.reset(cast<ObjectFile>(Bin.release()));
658 BytesInAddress = OF->getBytesInAddress();
663 auto ObjFormat = OF->getTripleObjectFormat();
667 if (
auto E = NamesSection.takeError())
669 auto CoverageSection =
672 if (
auto E = CoverageSection.takeError())
676 if (
auto EC = CoverageSection->getContents(CoverageMapping))
690 uint8_t BytesInAddress;
694 if (ObjectBuffer->getBuffer().startswith(TestingFormatMagic))
697 Coverage, BytesInAddress, Endian);
700 Coverage, BytesInAddress, Endian, Arch);
705 E = readCoverageMappingData<uint32_t, support::endianness::little>(
706 Reader->ProfileNames, Coverage, Reader->MappingRecords,
709 E = readCoverageMappingData<uint32_t, support::endianness::big>(
710 Reader->ProfileNames, Coverage, Reader->MappingRecords,
713 E = readCoverageMappingData<uint64_t, support::endianness::little>(
714 Reader->ProfileNames, Coverage, Reader->MappingRecords,
717 E = readCoverageMappingData<uint64_t, support::endianness::big>(
718 Reader->ProfileNames, Coverage, Reader->MappingRecords,
724 return std::move(Reader);
728 if (CurrentRecord >= MappingRecords.size())
731 FunctionsFilenames.clear();
733 MappingRegions.clear();
734 auto &R = MappingRecords[CurrentRecord];
737 makeArrayRef(Filenames).slice(R.FilenamesBegin, R.FilenamesSize),
739 if (
auto Err = Reader.
read())
Pass interface - Implemented by all 'passes'.
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
static const unsigned EncodingTagMask
Reader for the raw coverage mapping data.
This class represents lattice values for constants.
static Counter getZero()
Return the counter that represents the number zero.
void push_back(const T &Elt)
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
Checks if the given coverage mapping data is exported for an unused function.
std::string getInstrProfSectionName(InstrProfSectKind IPSK, Triple::ObjectFormatType OF, bool AddSegmentInfo=true)
Return the name of the profile section corresponding to IPSK.
A Counter expression is a value that represents an arithmetic operation with two counters.
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&... args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
Error takeError()
Take ownership of the stored error.
ArrayRef< CounterMappingRegion > MappingRegions
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
gvn Early GVN Hoisting of Expressions
Error readSize(uint64_t &Result)
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
amdgpu Simplify well known AMD library false Value Value const Twine & Name
A GapRegion is like a CodeRegion, but its count is only set as the line execution count when its the ...
Reader for the coverage mapping data that is emitted by the frontend and stored in an object file...
ArrayRef< T > makeArrayRef(const T &OneElt)
Construct an ArrayRef from a single element.
ArrayRef< CounterExpression > Expressions
Tagged union holding either a T or a Error.
static uint64_t readULEB128(WasmObjectFile::ReadContext &Ctx)
StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize)
Return function's PGO name from the function name's symbol address in the object file.
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
void dump(const Counter &C, raw_ostream &OS) const
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
StringRef CoverageMapping
Error readIntMax(uint64_t &Result, uint64_t MaxPlus1)
Error readNextRecord(CoverageMappingRecord &Record) override
ArrayRef< StringRef > Filenames
Coverage mapping information for a single function.
static Error readCoverageMappingData(InstrProfSymtab &ProfileNames, StringRef Data, std::vector< BinaryCoverageReader::ProfileMappingRecord > &Records, std::vector< StringRef > &Filenames)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
size_t alignmentAdjustment(const void *Ptr, size_t Alignment)
Returns the necessary adjustment for aligning Ptr to Alignment bytes, rounding up.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Reader for the raw coverage filenames.
Error readULEB128(uint64_t &Result)
A CodeRegion associates some code with a counter.
A Counter mapping context is used to connect the counters, expressions and the obtained counter value...
A Counter mapping region associates a source range with a specific counter.
Expected< bool > isDummy()
Error readString(StringRef &Result)
uint64_t decodeULEB128(const uint8_t *p, unsigned *n=nullptr, const uint8_t *end=nullptr, const char **error=nullptr)
Utility function to decode a ULEB128 value.
void consumeError(Error Err)
Consume a Error without doing anything.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Triple - Helper class for working with autoconf configuration names.
A file format agnostic iterator over coverage mapping data.
Error create(object::SectionRef &Section)
Create InstrProfSymtab from an object file section which contains function PGO names.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
print lazy value Lazy Value Info Printer Pass
static ErrorSuccess success()
Create a success value.
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
static Expected< SectionRef > lookupSection(ObjectFile &OF, StringRef Name)
static const unsigned EncodingExpansionRegionBit
static Error loadBinaryFormat(MemoryBufferRef ObjectBuffer, InstrProfSymtab &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian, StringRef Arch)
static const char * TestingFormatMagic
static Expected< std::unique_ptr< BinaryCoverageReader > > create(std::unique_ptr< MemoryBuffer > &ObjectBuffer, StringRef Arch)
An ExpansionRegion represents a file expansion region that associates a source range with the expansi...
A SkippedRegion represents a source range with code that was skipped by a preprocessor or similar mea...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
static StringRef readString(WasmObjectFile::ReadContext &Ctx)
static const unsigned EncodingCounterTagAndExpansionRegionTagBits
The mapping of profile information to coverage data.
static Error loadTestingFormat(StringRef Data, InstrProfSymtab &ProfileNames, StringRef &CoverageMapping, uint8_t &BytesInAddress, support::endianness &Endian)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const unsigned EncodingTagBits
static Expected< bool > isCoverageMappingDummy(uint64_t Hash, StringRef Mapping)
LLVM Value Representation.
Lightweight error class with error context and mandatory checking.
StringRef - Represent a constant reference to a string, i.e.
static Counter getExpression(unsigned ExpressionId)
Return the counter that corresponds to a specific addition counter expression.
A Counter is an abstract value that describes how to compute the execution count for a region of code...
static Counter getCounter(unsigned CounterId)
Return the counter that corresponds to a specific profile counter.