#include <system_error>
namespace llvm {
+class IndexedInstrProfReader;
namespace coverage {
+class ObjectFileCoverageMappingReader;
+
+class CoverageMapping;
struct CounterExpressions;
enum CoverageMappingVersion { CoverageMappingVersion1 };
ColumnStart(ColumnStart), LineEnd(LineEnd), ColumnEnd(ColumnEnd),
Kind(Kind), HasCodeBefore(HasCodeBefore) {}
+ inline std::pair<unsigned, unsigned> startLoc() const {
+ return std::pair<unsigned, unsigned>(LineStart, ColumnStart);
+ }
+
+ inline std::pair<unsigned, unsigned> endLoc() const {
+ return std::pair<unsigned, unsigned>(LineEnd, ColumnEnd);
+ }
+
bool operator<(const CounterMappingRegion &Other) const {
if (FileID != Other.FileID)
return FileID < Other.FileID;
- if (LineStart == Other.LineStart)
- return ColumnStart < Other.ColumnStart;
- return LineStart < Other.LineStart;
+ return startLoc() < Other.startLoc();
+ }
+
+ bool contains(const CounterMappingRegion &Other) const {
+ if (FileID != Other.FileID)
+ return false;
+ if (startLoc() > Other.startLoc())
+ return false;
+ if (endLoc() < Other.endLoc())
+ return false;
+ return true;
}
};
ErrorOr<int64_t> evaluate(const Counter &C) const;
};
+/// \brief Code coverage information for a single function.
+struct FunctionRecord {
+ /// \brief Raw function name.
+ std::string Name;
+ /// \brief Associated files.
+ std::vector<std::string> Filenames;
+ /// \brief Regions in the function along with their counts.
+ std::vector<CountedRegion> CountedRegions;
+
+ FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
+ : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
+};
+
+/// \brief Coverage information for a macro expansion or #included file.
+///
+/// When covered code has pieces that can be expanded for more detail, such as a
+/// preprocessor macro use and its definition, these are represented as
+/// expansions whose coverage can be looked up independently.
+struct ExpansionRecord {
+ /// \brief The abstract file this expansion covers.
+ unsigned FileID;
+ /// \brief The region that expands to this record.
+ const CountedRegion &Region;
+ /// \brief Coverage for the expansion.
+ const FunctionRecord &Function;
+
+ ExpansionRecord(const CountedRegion &Region,
+ const FunctionRecord &Function)
+ : FileID(Region.ExpandedFileID), Region(Region), Function(Function) {}
+};
+
+/// \brief The execution count information starting at a point in a file.
+///
+/// A sequence of CoverageSegments gives execution counts for a file in format
+/// that's simple to iterate through for processing.
+struct CoverageSegment {
+ /// \brief The line where this segment begins.
+ unsigned Line;
+ /// \brief The column where this segment begins.
+ unsigned Col;
+ /// \brief The execution count, or zero if no count was recorded.
+ uint64_t Count;
+ /// \brief When false, the segment was uninstrumented or skipped.
+ bool HasCount;
+ /// \brief Whether this enters a new region or returns to a previous count.
+ bool IsRegionEntry;
+
+ CoverageSegment(unsigned Line, unsigned Col, bool IsRegionEntry)
+ : Line(Line), Col(Col), Count(0), HasCount(false),
+ IsRegionEntry(IsRegionEntry) {}
+ void setCount(uint64_t NewCount) {
+ Count = NewCount;
+ HasCount = true;
+ }
+};
+
+/// \brief Coverage information to be processed or displayed.
+///
+/// This represents the coverage of an entire file, expansion, or function. It
+/// provides a sequence of CoverageSegments to iterate through, as well as the
+/// list of expansions that can be further processed.
+class CoverageData {
+ std::string Filename;
+ std::vector<CoverageSegment> Segments;
+ std::vector<ExpansionRecord> Expansions;
+ friend class CoverageMapping;
+
+public:
+ CoverageData() {}
+
+ CoverageData(StringRef Filename) : Filename(Filename) {}
+
+ CoverageData(CoverageData &&RHS)
+ : Filename(std::move(RHS.Filename)), Segments(std::move(RHS.Segments)),
+ Expansions(std::move(RHS.Expansions)) {}
+
+ /// \brief Get the name of the file this data covers.
+ StringRef getFilename() { return Filename; }
+
+ std::vector<CoverageSegment>::iterator begin() { return Segments.begin(); }
+ std::vector<CoverageSegment>::iterator end() { return Segments.end(); }
+ bool empty() { return Segments.empty(); }
+
+ /// \brief Expansions that can be further processed.
+ std::vector<ExpansionRecord> getExpansions() { return Expansions; }
+};
+
+/// \brief The mapping of profile information to coverage data.
+///
+/// This is the main interface to get coverage information, using a profile to
+/// fill out execution counts.
+class CoverageMapping {
+ std::vector<FunctionRecord> Functions;
+ unsigned MismatchedFunctionCount;
+
+ CoverageMapping() : MismatchedFunctionCount(0) {}
+
+public:
+ /// Load the coverage mapping using the given readers.
+ static ErrorOr<std::unique_ptr<CoverageMapping>>
+ load(ObjectFileCoverageMappingReader &CoverageReader,
+ IndexedInstrProfReader &ProfileReader);
+
+ /// \brief The number of functions that couldn't have their profiles mapped.
+ ///
+ /// This is a count of functions whose profile is out of date or otherwise
+ /// can't be associated with any coverage information.
+ unsigned getMismatchedCount() { return MismatchedFunctionCount; }
+
+ /// \brief Returns the list of files that are covered.
+ std::vector<StringRef> getUniqueSourceFiles();
+
+ /// \brief Get the coverage for a particular file.
+ ///
+ /// The given filename must be the name as recorded in the coverage
+ /// information. That is, only names returned from getUniqueSourceFiles will
+ /// yield a result.
+ CoverageData getCoverageForFile(StringRef Filename);
+
+ /// \brief Gets all of the functions covered by this profile.
+ ArrayRef<FunctionRecord> getCoveredFunctions() {
+ return ArrayRef<FunctionRecord>(Functions.data(), Functions.size());
+ }
+
+ /// \brief Get the list of function instantiations in the file.
+ ///
+ /// Fucntions that are instantiated more than once, such as C++ template
+ /// specializations, have distinct coverage records for each instantiation.
+ std::vector<const FunctionRecord *> getInstantiations(StringRef Filename);
+
+ /// \brief Get the coverage for a particular function.
+ CoverageData getCoverageForFunction(const FunctionRecord &Function);
+
+ /// \brief Get the coverage for an expansion within a coverage set.
+ CoverageData getCoverageForExpansion(const ExpansionRecord &Expansion);
+};
+
} // end namespace coverage
} // end namespace llvm