Generating the coverage map
rustc now generates the coverage map and can support (limited)
coverage report generation, at the function level.
Example:
$ BUILD=$HOME/rust/build/x86_64-unknown-linux-gnu
$ $BUILD/stage1/bin/rustc -Zinstrument-coverage \
$HOME/rust/src/test/run-make-fulldeps/instrument-coverage/main.rs
$ LLVM_PROFILE_FILE="main.profraw" ./main
called
$ $BUILD/llvm/bin/llvm-profdata merge -sparse main.profraw -o main.profdata
$ $BUILD/llvm/bin/llvm-cov show --instr-profile=main.profdata main
1| 1|pub fn will_be_called() {
2| 1| println!("called");
3| 1|}
4| |
5| 0|pub fn will_not_be_called() {
6| 0| println!("should not have been called");
7| 0|}
8| |
9| 1|fn main() {
10| 1| let less = 1;
11| 1| let more = 100;
12| 1|
13| 1| if less < more {
14| 1| will_be_called();
15| 1| } else {
16| 1| will_not_be_called();
17| 1| }
18| 1|}
This commit is contained in:
115
src/rustllvm/CoverageMappingWrapper.cpp
Normal file
115
src/rustllvm/CoverageMappingWrapper.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include "rustllvm.h"
|
||||
#include "llvm/ProfileData/Coverage/CoverageMapping.h"
|
||||
#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
extern "C" SmallVectorTemplateBase<coverage::CounterExpression>
|
||||
*LLVMRustCoverageSmallVectorCounterExpressionCreate() {
|
||||
return new SmallVector<coverage::CounterExpression, 32>();
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageSmallVectorCounterExpressionDispose(
|
||||
SmallVectorTemplateBase<coverage::CounterExpression> *Vector) {
|
||||
delete Vector;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageSmallVectorCounterExpressionAdd(
|
||||
SmallVectorTemplateBase<coverage::CounterExpression> *Expressions,
|
||||
coverage::CounterExpression::ExprKind Kind,
|
||||
unsigned LeftIndex,
|
||||
unsigned RightIndex) {
|
||||
auto LHS = coverage::Counter::getCounter(LeftIndex);
|
||||
auto RHS = coverage::Counter::getCounter(RightIndex);
|
||||
Expressions->push_back(coverage::CounterExpression { Kind, LHS, RHS });
|
||||
}
|
||||
|
||||
extern "C" SmallVectorTemplateBase<coverage::CounterMappingRegion>
|
||||
*LLVMRustCoverageSmallVectorCounterMappingRegionCreate() {
|
||||
return new SmallVector<coverage::CounterMappingRegion, 32>();
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageSmallVectorCounterMappingRegionDispose(
|
||||
SmallVectorTemplateBase<coverage::CounterMappingRegion> *Vector) {
|
||||
delete Vector;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageSmallVectorCounterMappingRegionAdd(
|
||||
SmallVectorTemplateBase<coverage::CounterMappingRegion> *MappingRegions,
|
||||
unsigned Index,
|
||||
unsigned FileID,
|
||||
unsigned LineStart,
|
||||
unsigned ColumnStart,
|
||||
unsigned LineEnd,
|
||||
unsigned ColumnEnd) {
|
||||
auto Counter = coverage::Counter::getCounter(Index);
|
||||
MappingRegions->push_back(coverage::CounterMappingRegion::makeRegion(
|
||||
Counter, FileID, LineStart,
|
||||
ColumnStart, LineEnd, ColumnEnd));
|
||||
|
||||
// FIXME(richkadel): As applicable, implement additional CounterMappingRegion types using the
|
||||
// static method alternatives to `coverage::CounterMappingRegion::makeRegion`:
|
||||
//
|
||||
// makeExpansion(unsigned FileID, unsigned ExpandedFileID, unsigned LineStart,
|
||||
// unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
|
||||
// makeSkipped(unsigned FileID, unsigned LineStart, unsigned ColumnStart,
|
||||
// unsigned LineEnd, unsigned ColumnEnd) {
|
||||
// makeGapRegion(Counter Count, unsigned FileID, unsigned LineStart,
|
||||
// unsigned ColumnStart, unsigned LineEnd, unsigned ColumnEnd) {
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteFilenamesSectionToBuffer(
|
||||
const char* const Filenames[],
|
||||
size_t FilenamesLen,
|
||||
RustStringRef BufferOut) {
|
||||
SmallVector<StringRef,32> FilenameRefs;
|
||||
for (size_t i = 0; i < FilenamesLen; i++) {
|
||||
FilenameRefs.push_back(StringRef(Filenames[i]));
|
||||
}
|
||||
auto FilenamesWriter = coverage::CoverageFilenamesSectionWriter(
|
||||
makeArrayRef(FilenameRefs));
|
||||
RawRustStringOstream OS(BufferOut);
|
||||
FilenamesWriter.write(OS);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteMappingToBuffer(
|
||||
const unsigned *VirtualFileMappingIDs,
|
||||
unsigned NumVirtualFileMappingIDs,
|
||||
const SmallVectorImpl<coverage::CounterExpression> *Expressions,
|
||||
SmallVectorImpl<coverage::CounterMappingRegion> *MappingRegions,
|
||||
RustStringRef BufferOut) {
|
||||
auto CoverageMappingWriter = coverage::CoverageMappingWriter(
|
||||
makeArrayRef(VirtualFileMappingIDs, NumVirtualFileMappingIDs),
|
||||
makeArrayRef(*Expressions),
|
||||
MutableArrayRef<coverage::CounterMappingRegion> { *MappingRegions });
|
||||
RawRustStringOstream OS(BufferOut);
|
||||
CoverageMappingWriter.write(OS);
|
||||
}
|
||||
|
||||
extern "C" uint64_t LLVMRustCoverageComputeHash(const char *Name) {
|
||||
StringRef NameRef(Name);
|
||||
return IndexedInstrProf::ComputeHash(NameRef);
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteSectionNameToString(LLVMModuleRef M,
|
||||
RustStringRef Str) {
|
||||
Triple TargetTriple(unwrap(M)->getTargetTriple());
|
||||
auto name = getInstrProfSectionName(IPSK_covmap,
|
||||
TargetTriple.getObjectFormat());
|
||||
RawRustStringOstream OS(Str);
|
||||
OS << name;
|
||||
}
|
||||
|
||||
extern "C" void LLVMRustCoverageWriteMappingVarNameToString(RustStringRef Str) {
|
||||
auto name = getCoverageMappingVarName();
|
||||
RawRustStringOstream OS(Str);
|
||||
OS << name;
|
||||
}
|
||||
|
||||
extern "C" uint32_t LLVMRustCoverageMappingVersion() {
|
||||
return coverage::CovMapVersion::CurrentVersion;
|
||||
}
|
||||
Reference in New Issue
Block a user