llvm-6502/tools/llvm-cov/SourceCoverageView.h
Alex Lorenz 6c7a6a1ba2 llvm-cov: add code coverage tool that's based on coverage mapping format and clang's pgo.
This commit expands llvm-cov's functionality by adding support for a new code coverage
tool that uses LLVM's coverage mapping format and clang's instrumentation based profiling.
The gcov compatible tool can be invoked by supplying the 'gcov' command as the first argument,
or by modifying the tool's name to end with 'gcov'.

Differential Revision: http://reviews.llvm.org/D4445


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216300 91177308-0d34-0410-b5e6-96231b3b80d8
2014-08-22 22:56:03 +00:00

214 lines
7.2 KiB
C++

//===- SourceCoverageView.h - Code coverage view for source code ----------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This class implements rendering for code coverage of source code.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_COV_SOURCECOVERAGEVIEW_H
#define LLVM_COV_SOURCECOVERAGEVIEW_H
#include "CoverageViewOptions.h"
#include "SourceCoverageDataManager.h"
#include "llvm/ProfileData/CoverageMapping.h"
#include "llvm/Support/MemoryBuffer.h"
#include <vector>
namespace llvm {
/// \brief A code coverage view of a specific source file.
/// It can have embedded coverage views.
class SourceCoverageView {
public:
enum SubViewKind { View, ExpansionView, InstantiationView };
/// \brief Coverage information for a single line.
struct LineCoverageInfo {
uint64_t ExecutionCount;
unsigned RegionCount;
bool Mapped;
LineCoverageInfo() : ExecutionCount(0), RegionCount(0), Mapped(false) {}
bool isMapped() const { return Mapped; }
bool hasMultipleRegions() const { return RegionCount > 1; }
void addRegionStartCount(uint64_t Count) {
Mapped = true;
ExecutionCount = Count;
++RegionCount;
}
void addRegionCount(uint64_t Count) {
Mapped = true;
ExecutionCount = Count;
}
};
/// \brief A marker that points at the start
/// of a specific mapping region.
struct RegionMarker {
unsigned Line, Column;
uint64_t ExecutionCount;
RegionMarker(unsigned Line, unsigned Column, uint64_t Value)
: Line(Line), Column(Column), ExecutionCount(Value) {}
};
/// \brief A single line source range used to
/// render highlighted text.
struct HighlightRange {
enum HighlightKind {
/// The code that wasn't executed.
NotCovered,
/// The region of code that was expanded.
Expanded
};
HighlightKind Kind;
unsigned Line;
unsigned ColumnStart;
unsigned ColumnEnd;
HighlightRange(unsigned Line, unsigned ColumnStart, unsigned ColumnEnd,
HighlightKind Kind = NotCovered)
: Kind(Kind), Line(Line), ColumnStart(ColumnStart),
ColumnEnd(ColumnEnd) {}
bool operator<(const HighlightRange &Other) const {
if (Line == Other.Line)
return ColumnStart < Other.ColumnStart;
return Line < Other.Line;
}
bool columnStartOverlaps(const HighlightRange &Other) const {
return ColumnStart <= Other.ColumnStart && ColumnEnd > Other.ColumnStart;
}
bool columnEndOverlaps(const HighlightRange &Other) const {
return ColumnEnd >= Other.ColumnEnd && ColumnStart < Other.ColumnEnd;
}
bool contains(const HighlightRange &Other) const {
if (Line != Other.Line)
return false;
return ColumnStart <= Other.ColumnStart && ColumnEnd >= Other.ColumnEnd;
}
bool overlaps(const HighlightRange &Other) const {
if (Line != Other.Line)
return false;
return columnStartOverlaps(Other) || columnEndOverlaps(Other);
}
};
private:
const MemoryBuffer &File;
const CoverageViewOptions &Options;
unsigned LineStart, LineCount;
SubViewKind Kind;
coverage::CounterMappingRegion ExpansionRegion;
std::vector<std::unique_ptr<SourceCoverageView>> Children;
std::vector<LineCoverageInfo> LineStats;
std::vector<HighlightRange> HighlightRanges;
std::vector<RegionMarker> Markers;
StringRef FunctionName;
/// \brief Create the line coverage information using the coverage data.
void createLineCoverageInfo(SourceCoverageDataManager &Data);
/// \brief Create the line highlighting ranges using the coverage data.
void createHighlightRanges(SourceCoverageDataManager &Data);
/// \brief Create the region markers using the coverage data.
void createRegionMarkers(SourceCoverageDataManager &Data);
/// \brief Sort children by the starting location.
void sortChildren();
/// \brief Return a highlight range for the expansion region of this view.
HighlightRange getExpansionHighlightRange() const;
/// \brief Render a source line with highlighting.
void renderLine(raw_ostream &OS, StringRef Line,
ArrayRef<HighlightRange> Ranges);
void renderOffset(raw_ostream &OS, unsigned I);
void renderViewDivider(unsigned Offset, unsigned Length, raw_ostream &OS);
/// \brief Render the line's execution count column.
void renderLineCoverageColumn(raw_ostream &OS, const LineCoverageInfo &Line);
/// \brief Render the line number column.
void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo);
/// \brief Render all the region's execution counts on a line.
void renderRegionMarkers(raw_ostream &OS, ArrayRef<RegionMarker> Regions);
static const unsigned LineCoverageColumnWidth = 7;
static const unsigned LineNumberColumnWidth = 5;
public:
SourceCoverageView(const MemoryBuffer &File,
const CoverageViewOptions &Options)
: File(File), Options(Options), LineStart(1), Kind(View),
ExpansionRegion(coverage::Counter(), 0, 0, 0, 0, 0) {
LineCount = File.getBuffer().count('\n') + 1;
}
SourceCoverageView(const MemoryBuffer &File,
const CoverageViewOptions &Options, unsigned LineStart,
unsigned LineEnd)
: File(File), Options(Options), LineStart(LineStart),
LineCount(LineEnd - LineStart + 1), Kind(View),
ExpansionRegion(coverage::Counter(), 0, 0, 0, 0, 0) {}
SourceCoverageView(SourceCoverageView &Parent, unsigned LineStart,
unsigned LineEnd, StringRef FunctionName)
: File(Parent.File), Options(Parent.Options), LineStart(LineStart),
LineCount(LineEnd - LineStart + 1), Kind(InstantiationView),
ExpansionRegion(coverage::Counter(), 0, LineEnd, 0, LineEnd, 0),
FunctionName(FunctionName) {}
SourceCoverageView(const MemoryBuffer &File,
const CoverageViewOptions &Options, unsigned LineStart,
unsigned LineEnd,
const coverage::CounterMappingRegion &ExpansionRegion)
: File(File), Options(Options), LineStart(LineStart),
LineCount(LineEnd - LineStart + 1), Kind(ExpansionView),
ExpansionRegion(ExpansionRegion) {}
const CoverageViewOptions &getOptions() const { return Options; }
bool isExpansionSubView() const { return Kind == ExpansionView; }
bool isInstantiationSubView() const { return Kind == InstantiationView; }
/// \brief Return the line number after which the subview expansion is shown.
unsigned getSubViewsExpansionLine() const {
return ExpansionRegion.LineStart;
}
void addChild(std::unique_ptr<SourceCoverageView> View) {
Children.push_back(std::move(View));
}
/// \brief Print the code coverage information for a specific
/// portion of a source file to the output stream.
void render(raw_ostream &OS, unsigned Offset = 0);
/// \brief Load the coverage information required for rendering
/// from the mapping regions in the data manager.
void load(SourceCoverageDataManager &Data);
};
} // namespace llvm
#endif // LLVM_COV_SOURCECOVERAGEVIEW_H