Skip to content

Commit

Permalink
Auto merge of #74091 - richkadel:llvm-coverage-map-gen-4, r=tmandry
Browse files Browse the repository at this point in the history
Generating the coverage map

@tmandry @wesleywiser

rustc now generates the coverage map and can support (limited)
coverage report generation, at the function level.

Example commands to generate a coverage report:
```shell
$ 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
```
![rust coverage report only 20200706](https://user-images.githubusercontent.com/3827298/86697299-1cbe8f80-bfc3-11ea-8955-451b48626991.png)

r? @wesleywiser

Rust compiler MCP rust-lang/compiler-team#278
Relevant issue: #34701 - Implement support for LLVMs code coverage instrumentation
  • Loading branch information
bors committed Jul 19, 2020
2 parents 0701419 + a6f8b8a commit 47ea6d9
Show file tree
Hide file tree
Showing 52 changed files with 1,724 additions and 262 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2821,6 +2821,13 @@ dependencies = [
"rls-span",
]

[[package]]
name = "rust-demangler"
version = "0.0.0"
dependencies = [
"rustc-demangle",
]

[[package]]
name = "rustbook"
version = "0.1.0"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ members = [
"src/tools/remote-test-client",
"src/tools/remote-test-server",
"src/tools/rust-installer",
"src/tools/rust-demangler",
"src/tools/cargo",
"src/tools/rustdoc",
"src/tools/rls",
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,7 @@ impl<'a> Builder<'a> {
tool::Cargo,
tool::Rls,
tool::RustAnalyzer,
tool::RustDemangler,
tool::Rustdoc,
tool::Clippy,
tool::CargoClippy,
Expand Down
4 changes: 4 additions & 0 deletions src/bootstrap/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1022,6 +1022,10 @@ impl Step for Compiletest {
cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
}

if mode == "run-make" && suite.ends_with("fulldeps") {
cmd.arg("--rust-demangler-path").arg(builder.tool_exe(Tool::RustDemangler));
}

cmd.arg("--src-base").arg(builder.src.join("src/test").join(suite));
cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite));
cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target));
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ bootstrap_tool!(
Compiletest, "src/tools/compiletest", "compiletest", is_unstable_tool = true;
BuildManifest, "src/tools/build-manifest", "build-manifest";
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client";
RustDemangler, "src/tools/rust-demangler", "rust-demangler";
RustInstaller, "src/tools/rust-installer", "fabricate", is_external_tool = true;
RustdocTheme, "src/tools/rustdoc-themes", "rustdoc-themes";
ExpandYamlAnchors, "src/tools/expand-yaml-anchors", "expand-yaml-anchors";
Expand Down
12 changes: 11 additions & 1 deletion src/libcore/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1958,15 +1958,23 @@ extern "rust-intrinsic" {
/// Internal placeholder for injecting code coverage counters when the "instrument-coverage"
/// option is enabled. The placeholder is replaced with `llvm.instrprof.increment` during code
/// generation.
#[cfg(not(bootstrap))]
#[lang = "count_code_region"]
pub fn count_code_region(index: u32, start_byte_pos: u32, end_byte_pos: u32);
pub fn count_code_region(
function_source_hash: u64,
index: u32,
start_byte_pos: u32,
end_byte_pos: u32,
);

/// Internal marker for code coverage expressions, injected into the MIR when the
/// "instrument-coverage" option is enabled. This intrinsic is not converted into a
/// backend intrinsic call, but its arguments are extracted during the production of a
/// "coverage map", which is injected into the generated code, as additional data.
/// This marker identifies a code region and two other counters or counter expressions
/// whose sum is the number of times the code region was executed.
#[cfg(not(bootstrap))]
#[lang = "coverage_counter_add"]
pub fn coverage_counter_add(
index: u32,
left_index: u32,
Expand All @@ -1978,6 +1986,8 @@ extern "rust-intrinsic" {
/// This marker identifies a code region and two other counters or counter expressions
/// whose difference is the number of times the code region was executed.
/// (See `coverage_counter_add` for more information.)
#[cfg(not(bootstrap))]
#[lang = "coverage_counter_subtract"]
pub fn coverage_counter_subtract(
index: u32,
left_index: u32,
Expand Down
3 changes: 3 additions & 0 deletions src/librustc_codegen_llvm/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
return;
}

// FIXME(richkadel): Make sure probestack plays nice with `-Z instrument-coverage`
// or disable it if not, similar to above early exits.

// Flag our internal `__rust_probestack` function as the stack probe symbol.
// This is defined in the `compiler-builtins` crate for each architecture.
llvm::AddFunctionAttrStringValue(
Expand Down
11 changes: 6 additions & 5 deletions src/librustc_codegen_llvm/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,17 +144,18 @@ pub fn compile_codegen_unit(
}
}

// Finalize code coverage by injecting the coverage map. Note, the coverage map will
// also be added to the `llvm.used` variable, created next.
if cx.sess().opts.debugging_opts.instrument_coverage {
cx.coverageinfo_finalize();
}

// Create the llvm.used variable
// This variable has type [N x i8*] and is stored in the llvm.metadata section
if !cx.used_statics().borrow().is_empty() {
cx.create_used_variable()
}

// Finalize code coverage by injecting the coverage map
if cx.sess().opts.debugging_opts.instrument_coverage {
cx.coverageinfo_finalize();
}

// Finalize debuginfo
if cx.sess().opts.debuginfo != DebugInfo::None {
cx.debuginfo_finalize();
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_codegen_llvm/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1060,7 +1060,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn_name, hash, num_counters, index
);

let llfn = unsafe { llvm::LLVMRustGetInstrprofIncrementIntrinsic(self.cx().llmod) };
let llfn = unsafe { llvm::LLVMRustGetInstrProfIncrementIntrinsic(self.cx().llmod) };
let args = &[fn_name, hash, num_counters, index];
let args = self.check_call("call", llfn, args);

Expand Down
10 changes: 7 additions & 3 deletions src/librustc_codegen_llvm/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,10 +493,14 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
}

if attrs.flags.contains(CodegenFnAttrFlags::USED) {
// This static will be stored in the llvm.used variable which is an array of i8*
let cast = llvm::LLVMConstPointerCast(g, self.type_i8p());
self.used_statics.borrow_mut().push(cast);
self.add_used_global(g);
}
}
}

/// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*.
fn add_used_global(&self, global: &'ll Value) {
let cast = unsafe { llvm::LLVMConstPointerCast(global, self.type_i8p()) };
self.used_statics.borrow_mut().push(cast);
}
}
Loading

0 comments on commit 47ea6d9

Please sign in to comment.