about summary refs log tree commit diff
path: root/src/rustllvm/CoverageMappingWrapper.cpp
diff options
context:
space:
mode:
authorRich Kadel <richkadel@google.com>2020-07-02 11:27:15 -0700
committerRich Kadel <richkadel@google.com>2020-07-17 11:49:35 -0700
commita6f8b8a2116f0ea7e31d572d3120508678ed8079 (patch)
treeea4c018d3684b3990d2d01bc02efa923360c7129 /src/rustllvm/CoverageMappingWrapper.cpp
parentc2dbebd3d4ad21e80ef4e7535dd1e868aaad7e50 (diff)
downloadrust-a6f8b8a2116f0ea7e31d572d3120508678ed8079.tar.gz
rust-a6f8b8a2116f0ea7e31d572d3120508678ed8079.zip
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|}
Diffstat (limited to 'src/rustllvm/CoverageMappingWrapper.cpp')
-rw-r--r--src/rustllvm/CoverageMappingWrapper.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/rustllvm/CoverageMappingWrapper.cpp b/src/rustllvm/CoverageMappingWrapper.cpp
new file mode 100644
index 00000000000..c6c4cdb5562
--- /dev/null
+++ b/src/rustllvm/CoverageMappingWrapper.cpp
@@ -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;
+}