Skip to content

Commit 953e240

Browse files
committed
llvm-cov: Disentangle the coverage data logic from the display (NFC)
This splits the logic for actually looking up coverage information from the logic that displays it. These were tangled rather thoroughly so this change is a bit large, but it mostly consists of moving things around. The coverage lookup logic itself now lives in the library, rather than being spread between the library and the tool. llvm-svn: 218184
1 parent f584649 commit 953e240

14 files changed

+542
-479
lines changed

llvm/include/llvm/ProfileData/CoverageMapping.h

+130-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@
2121
#include <system_error>
2222

2323
namespace llvm {
24+
class IndexedInstrProfReader;
2425
namespace coverage {
2526

27+
class ObjectFileCoverageMappingReader;
28+
29+
class CoverageMapping;
2630
struct CounterExpressions;
2731

2832
enum CoverageMappingVersion { CoverageMappingVersion1 };
@@ -217,18 +221,142 @@ class CounterMappingContext {
217221
};
218222

219223
/// \brief Code coverage information for a single function.
220-
struct FunctionCoverageMapping {
224+
struct FunctionRecord {
221225
/// \brief Raw function name.
222226
std::string Name;
223227
/// \brief Associated files.
224228
std::vector<std::string> Filenames;
225229
/// \brief Regions in the function along with their counts.
226230
std::vector<CountedRegion> CountedRegions;
227231

228-
FunctionCoverageMapping(StringRef Name, ArrayRef<StringRef> Filenames)
232+
FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
229233
: Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
230234
};
231235

236+
/// \brief Coverage information for a macro expansion or #included file.
237+
///
238+
/// When covered code has pieces that can be expanded for more detail, such as a
239+
/// preprocessor macro use and its definition, these are represented as
240+
/// expansions whose coverage can be looked up independently.
241+
struct ExpansionRecord {
242+
/// \brief The abstract file this expansion covers.
243+
unsigned FileID;
244+
/// \brief The region that expands to this record.
245+
const CountedRegion &Region;
246+
/// \brief Coverage for the expansion.
247+
const FunctionRecord &Function;
248+
249+
ExpansionRecord(const CountedRegion &Region,
250+
const FunctionRecord &Function)
251+
: FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
252+
};
253+
254+
/// \brief The execution count information starting at a point in a file.
255+
///
256+
/// A sequence of CoverageSegments gives execution counts for a file in format
257+
/// that's simple to iterate through for processing.
258+
struct CoverageSegment {
259+
/// \brief The line where this segment begins.
260+
unsigned Line;
261+
/// \brief The column where this segment begins.
262+
unsigned Col;
263+
/// \brief The execution count, or zero if no count was recorded.
264+
uint64_t Count;
265+
/// \brief When false, the segment was uninstrumented or skipped.
266+
bool HasCount;
267+
/// \brief Whether this enters a new region or returns to a previous count.
268+
bool IsRegionEntry;
269+
270+
CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
271+
: Line(Line), Col(Col), Count(0), HasCount(false),
272+
IsRegionEntry(IsRegionEntry) {}
273+
void setCount(uint64_t NewCount) {
274+
Count = NewCount;
275+
HasCount = true;
276+
}
277+
};
278+
279+
/// \brief Coverage information to be processed or displayed.
280+
///
281+
/// This represents the coverage of an entire file, expansion, or function. It
282+
/// provides a sequence of CoverageSegments to iterate through, as well as the
283+
/// list of expansions that can be further processed.
284+
class CoverageData {
285+
std::string Filename;
286+
std::vector<CoverageSegment> Segments;
287+
std::vector<ExpansionRecord> Expansions;
288+
friend class CoverageMapping;
289+
290+
public:
291+
CoverageData() {}
292+
293+
CoverageData(StringRef Filename) : Filename(Filename) {}
294+
295+
CoverageData(CoverageData &&RHS)
296+
: Filename(std::move(RHS.Filename)), Segments(std::move(RHS.Segments)),
297+
Expansions(std::move(RHS.Expansions)) {}
298+
299+
/// \brief Get the name of the file this data covers.
300+
StringRef getFilename() { return Filename; }
301+
302+
std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); }
303+
std::vector<CoverageSegment>::iterator end() { return Segments.end(); }
304+
bool empty() { return Segments.empty(); }
305+
306+
/// \brief Expansions that can be further processed.
307+
std::vector<ExpansionRecord> getExpansions() { return Expansions; }
308+
};
309+
310+
/// \brief The mapping of profile information to coverage data.
311+
///
312+
/// This is the main interface to get coverage information, using a profile to
313+
/// fill out execution counts.
314+
class CoverageMapping {
315+
std::vector<FunctionRecord> Functions;
316+
unsigned MismatchedFunctionCount;
317+
318+
CoverageMapping() : MismatchedFunctionCount(0) {}
319+
320+
public:
321+
/// Load the coverage mapping using the given readers.
322+
static ErrorOr<std::unique_ptr<CoverageMapping>>
323+
load(ObjectFileCoverageMappingReader &CoverageReader,
324+
IndexedInstrProfReader &ProfileReader);
325+
326+
/// \brief The number of functions that couldn't have their profiles mapped.
327+
///
328+
/// This is a count of functions whose profile is out of date or otherwise
329+
/// can't be associated with any coverage information.
330+
unsigned getMismatchedCount() { return MismatchedFunctionCount; }
331+
332+
/// \brief Returns the list of files that are covered.
333+
std::vector<StringRef> getUniqueSourceFiles();
334+
335+
/// \brief Get the coverage for a particular file.
336+
///
337+
/// The given filename must be the name as recorded in the coverage
338+
/// information. That is, only names returned from getUniqueSourceFiles will
339+
/// yield a result.
340+
CoverageData getCoverageForFile(StringRef Filename);
341+
342+
/// \brief Gets all of the functions covered by this profile.
343+
ArrayRef<FunctionRecord> getCoveredFunctions() {
344+
return ArrayRef<FunctionRecord>(Functions.data(), Functions.size());
345+
}
346+
347+
/// \brief Get the list of function instantiations in the file.
348+
///
349+
/// Fucntions that are instantiated more than once, such as C++ template
350+
/// specializations, have distinct coverage records for each instantiation.
351+
std::vector<const FunctionRecord *> getInstantiations(StringRef Filename);
352+
353+
/// \brief Get the coverage for a particular function.
354+
CoverageData getCoverageForFunction(const FunctionRecord &Function);
355+
356+
/// \brief Get the coverage for an expansion within a coverage set.
357+
CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion);
358+
};
359+
232360
} // end namespace coverage
233361
} // end namespace llvm
234362

0 commit comments

Comments
 (0)