1321369Sdim//===- CoverageMappingReader.h - Code coverage mapping reader ---*- C++ -*-===// 2303231Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6303231Sdim// 7303231Sdim//===----------------------------------------------------------------------===// 8303231Sdim// 9303231Sdim// This file contains support for reading coverage mapping data for 10303231Sdim// instrumentation based coverage. 11303231Sdim// 12303231Sdim//===----------------------------------------------------------------------===// 13303231Sdim 14321369Sdim#ifndef LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H 15321369Sdim#define LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H 16303231Sdim 17303231Sdim#include "llvm/ADT/ArrayRef.h" 18303231Sdim#include "llvm/ADT/StringRef.h" 19303231Sdim#include "llvm/ProfileData/Coverage/CoverageMapping.h" 20303231Sdim#include "llvm/ProfileData/InstrProf.h" 21321369Sdim#include "llvm/Support/Error.h" 22303231Sdim#include "llvm/Support/MemoryBuffer.h" 23321369Sdim#include <cstddef> 24321369Sdim#include <cstdint> 25303231Sdim#include <iterator> 26321369Sdim#include <memory> 27321369Sdim#include <vector> 28303231Sdim 29303231Sdimnamespace llvm { 30303231Sdimnamespace coverage { 31303231Sdim 32303231Sdimclass CoverageMappingReader; 33303231Sdim 34341825Sdim/// Coverage mapping information for a single function. 35303231Sdimstruct CoverageMappingRecord { 36303231Sdim StringRef FunctionName; 37303231Sdim uint64_t FunctionHash; 38303231Sdim ArrayRef<StringRef> Filenames; 39303231Sdim ArrayRef<CounterExpression> Expressions; 40303231Sdim ArrayRef<CounterMappingRegion> MappingRegions; 41303231Sdim}; 42303231Sdim 43341825Sdim/// A file format agnostic iterator over coverage mapping data. 44303231Sdimclass CoverageMappingIterator 45303231Sdim : public std::iterator<std::input_iterator_tag, CoverageMappingRecord> { 46327952Sdim CoverageMappingReader *Reader; 47303231Sdim CoverageMappingRecord Record; 48327952Sdim coveragemap_error ReadErr; 49303231Sdim 50303231Sdim void increment(); 51303231Sdim 52303231Sdimpublic: 53327952Sdim CoverageMappingIterator() 54327952Sdim : Reader(nullptr), Record(), ReadErr(coveragemap_error::success) {} 55321369Sdim 56327952Sdim CoverageMappingIterator(CoverageMappingReader *Reader) 57327952Sdim : Reader(Reader), Record(), ReadErr(coveragemap_error::success) { 58303231Sdim increment(); 59303231Sdim } 60303231Sdim 61327952Sdim ~CoverageMappingIterator() { 62327952Sdim if (ReadErr != coveragemap_error::success) 63327952Sdim llvm_unreachable("Unexpected error in coverage mapping iterator"); 64327952Sdim } 65327952Sdim 66303231Sdim CoverageMappingIterator &operator++() { 67303231Sdim increment(); 68303231Sdim return *this; 69303231Sdim } 70303231Sdim bool operator==(const CoverageMappingIterator &RHS) { 71303231Sdim return Reader == RHS.Reader; 72303231Sdim } 73303231Sdim bool operator!=(const CoverageMappingIterator &RHS) { 74303231Sdim return Reader != RHS.Reader; 75303231Sdim } 76327952Sdim Expected<CoverageMappingRecord &> operator*() { 77327952Sdim if (ReadErr != coveragemap_error::success) { 78327952Sdim auto E = make_error<CoverageMapError>(ReadErr); 79327952Sdim ReadErr = coveragemap_error::success; 80327952Sdim return std::move(E); 81327952Sdim } 82327952Sdim return Record; 83327952Sdim } 84327952Sdim Expected<CoverageMappingRecord *> operator->() { 85327952Sdim if (ReadErr != coveragemap_error::success) { 86327952Sdim auto E = make_error<CoverageMapError>(ReadErr); 87327952Sdim ReadErr = coveragemap_error::success; 88327952Sdim return std::move(E); 89327952Sdim } 90327952Sdim return &Record; 91327952Sdim } 92303231Sdim}; 93303231Sdim 94303231Sdimclass CoverageMappingReader { 95303231Sdimpublic: 96321369Sdim virtual ~CoverageMappingReader() = default; 97321369Sdim 98303231Sdim virtual Error readNextRecord(CoverageMappingRecord &Record) = 0; 99303231Sdim CoverageMappingIterator begin() { return CoverageMappingIterator(this); } 100303231Sdim CoverageMappingIterator end() { return CoverageMappingIterator(); } 101303231Sdim}; 102303231Sdim 103341825Sdim/// Base class for the raw coverage mapping and filenames data readers. 104303231Sdimclass RawCoverageReader { 105303231Sdimprotected: 106303231Sdim StringRef Data; 107303231Sdim 108303231Sdim RawCoverageReader(StringRef Data) : Data(Data) {} 109303231Sdim 110303231Sdim Error readULEB128(uint64_t &Result); 111303231Sdim Error readIntMax(uint64_t &Result, uint64_t MaxPlus1); 112303231Sdim Error readSize(uint64_t &Result); 113303231Sdim Error readString(StringRef &Result); 114303231Sdim}; 115303231Sdim 116341825Sdim/// Reader for the raw coverage filenames. 117303231Sdimclass RawCoverageFilenamesReader : public RawCoverageReader { 118303231Sdim std::vector<StringRef> &Filenames; 119303231Sdim 120321369Sdimpublic: 121321369Sdim RawCoverageFilenamesReader(StringRef Data, std::vector<StringRef> &Filenames) 122321369Sdim : RawCoverageReader(Data), Filenames(Filenames) {} 123303231Sdim RawCoverageFilenamesReader(const RawCoverageFilenamesReader &) = delete; 124303231Sdim RawCoverageFilenamesReader & 125303231Sdim operator=(const RawCoverageFilenamesReader &) = delete; 126303231Sdim 127303231Sdim Error read(); 128303231Sdim}; 129303231Sdim 130341825Sdim/// Checks if the given coverage mapping data is exported for 131303231Sdim/// an unused function. 132303231Sdimclass RawCoverageMappingDummyChecker : public RawCoverageReader { 133303231Sdimpublic: 134303231Sdim RawCoverageMappingDummyChecker(StringRef MappingData) 135303231Sdim : RawCoverageReader(MappingData) {} 136303231Sdim 137303231Sdim Expected<bool> isDummy(); 138303231Sdim}; 139303231Sdim 140341825Sdim/// Reader for the raw coverage mapping data. 141303231Sdimclass RawCoverageMappingReader : public RawCoverageReader { 142303231Sdim ArrayRef<StringRef> TranslationUnitFilenames; 143303231Sdim std::vector<StringRef> &Filenames; 144303231Sdim std::vector<CounterExpression> &Expressions; 145303231Sdim std::vector<CounterMappingRegion> &MappingRegions; 146303231Sdim 147303231Sdimpublic: 148303231Sdim RawCoverageMappingReader(StringRef MappingData, 149303231Sdim ArrayRef<StringRef> TranslationUnitFilenames, 150303231Sdim std::vector<StringRef> &Filenames, 151303231Sdim std::vector<CounterExpression> &Expressions, 152303231Sdim std::vector<CounterMappingRegion> &MappingRegions) 153303231Sdim : RawCoverageReader(MappingData), 154303231Sdim TranslationUnitFilenames(TranslationUnitFilenames), 155303231Sdim Filenames(Filenames), Expressions(Expressions), 156303231Sdim MappingRegions(MappingRegions) {} 157321369Sdim RawCoverageMappingReader(const RawCoverageMappingReader &) = delete; 158321369Sdim RawCoverageMappingReader & 159321369Sdim operator=(const RawCoverageMappingReader &) = delete; 160303231Sdim 161303231Sdim Error read(); 162303231Sdim 163303231Sdimprivate: 164303231Sdim Error decodeCounter(unsigned Value, Counter &C); 165303231Sdim Error readCounter(Counter &C); 166303231Sdim Error 167303231Sdim readMappingRegionsSubArray(std::vector<CounterMappingRegion> &MappingRegions, 168303231Sdim unsigned InferredFileID, size_t NumFileIDs); 169303231Sdim}; 170303231Sdim 171341825Sdim/// Reader for the coverage mapping data that is emitted by the 172303231Sdim/// frontend and stored in an object file. 173303231Sdimclass BinaryCoverageReader : public CoverageMappingReader { 174303231Sdimpublic: 175303231Sdim struct ProfileMappingRecord { 176303231Sdim CovMapVersion Version; 177303231Sdim StringRef FunctionName; 178303231Sdim uint64_t FunctionHash; 179303231Sdim StringRef CoverageMapping; 180303231Sdim size_t FilenamesBegin; 181303231Sdim size_t FilenamesSize; 182303231Sdim 183303231Sdim ProfileMappingRecord(CovMapVersion Version, StringRef FunctionName, 184303231Sdim uint64_t FunctionHash, StringRef CoverageMapping, 185303231Sdim size_t FilenamesBegin, size_t FilenamesSize) 186303231Sdim : Version(Version), FunctionName(FunctionName), 187303231Sdim FunctionHash(FunctionHash), CoverageMapping(CoverageMapping), 188303231Sdim FilenamesBegin(FilenamesBegin), FilenamesSize(FilenamesSize) {} 189303231Sdim }; 190303231Sdim 191303231Sdimprivate: 192303231Sdim std::vector<StringRef> Filenames; 193303231Sdim std::vector<ProfileMappingRecord> MappingRecords; 194303231Sdim InstrProfSymtab ProfileNames; 195321369Sdim size_t CurrentRecord = 0; 196303231Sdim std::vector<StringRef> FunctionsFilenames; 197303231Sdim std::vector<CounterExpression> Expressions; 198303231Sdim std::vector<CounterMappingRegion> MappingRegions; 199303231Sdim 200321369Sdim BinaryCoverageReader() = default; 201321369Sdim 202321369Sdimpublic: 203303231Sdim BinaryCoverageReader(const BinaryCoverageReader &) = delete; 204303231Sdim BinaryCoverageReader &operator=(const BinaryCoverageReader &) = delete; 205303231Sdim 206353358Sdim static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>> 207353358Sdim create(MemoryBufferRef ObjectBuffer, StringRef Arch, 208353358Sdim SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers); 209353358Sdim 210303231Sdim static Expected<std::unique_ptr<BinaryCoverageReader>> 211353358Sdim createCoverageReaderFromBuffer(StringRef Coverage, 212353358Sdim InstrProfSymtab &&ProfileNames, 213353358Sdim uint8_t BytesInAddress, 214353358Sdim support::endianness Endian); 215303231Sdim 216303231Sdim Error readNextRecord(CoverageMappingRecord &Record) override; 217303231Sdim}; 218303231Sdim 219303231Sdim} // end namespace coverage 220303231Sdim} // end namespace llvm 221303231Sdim 222321369Sdim#endif // LLVM_PROFILEDATA_COVERAGE_COVERAGEMAPPINGREADER_H 223