Skip to content

Commit 8cf4f94

Browse files
committed
coverage: Add -Zcoverage-options for fine control of coverage instrumentation
This new nightly-only flag can be used to toggle fine-grained flags that control the details of coverage instrumentation. Currently the only supported flag value is `branch`, which is a placeholder for upcoming support for branch coverage. Other flag values can be added in the future, to prototype proposed new behaviour, or to enable special non-default behaviour.
1 parent fb5cddc commit 8cf4f94

File tree

6 files changed

+72
-11
lines changed

6 files changed

+72
-11
lines changed

compiler/rustc_session/src/config.rs

+20-6
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,19 @@ pub enum InstrumentCoverage {
143143
Yes,
144144
}
145145

146+
/// Individual flag values controlled by `-Z coverage-options`.
147+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
148+
pub struct CoverageOptions {
149+
/// Add branch coverage instrumentation (placeholder flag; not yet implemented).
150+
pub branch: bool,
151+
}
152+
153+
impl Default for CoverageOptions {
154+
fn default() -> Self {
155+
Self { branch: false }
156+
}
157+
}
158+
146159
/// Settings for `-Z instrument-xray` flag.
147160
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
148161
pub struct InstrumentXRay {
@@ -3168,12 +3181,12 @@ pub enum WasiExecModel {
31683181
/// how the hash should be calculated when adding a new command-line argument.
31693182
pub(crate) mod dep_tracking {
31703183
use super::{
3171-
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CrateType, DebugInfo,
3172-
DebugInfoCompression, ErrorOutputType, FunctionReturn, InliningThreshold,
3173-
InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, LtoCli,
3174-
NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius,
3175-
RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
3176-
SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
3184+
BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions,
3185+
CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FunctionReturn,
3186+
InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
3187+
LtoCli, NextSolverConfig, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
3188+
Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
3189+
SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, WasiExecModel,
31773190
};
31783191
use crate::lint;
31793192
use crate::utils::NativeLib;
@@ -3243,6 +3256,7 @@ pub(crate) mod dep_tracking {
32433256
CodeModel,
32443257
TlsModel,
32453258
InstrumentCoverage,
3259+
CoverageOptions,
32463260
InstrumentXRay,
32473261
CrateType,
32483262
MergeFunctions,

compiler/rustc_session/src/options.rs

+24-5
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,7 @@ mod desc {
396396
pub const parse_optimization_fuel: &str = "crate=integer";
397397
pub const parse_dump_mono_stats: &str = "`markdown` (default) or `json`";
398398
pub const parse_instrument_coverage: &str = parse_bool;
399+
pub const parse_coverage_options: &str = "`branch` or `no-branch`";
399400
pub const parse_instrument_xray: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), or a comma separated list of settings: `always` or `never` (mutually exclusive), `ignore-loops`, `instruction-threshold=N`, `skip-entry`, `skip-exit`";
400401
pub const parse_unpretty: &str = "`string` or `string=string`";
401402
pub const parse_treat_err_as_bug: &str = "either no value or a non-negative number";
@@ -938,6 +939,24 @@ mod parse {
938939
true
939940
}
940941

942+
pub(crate) fn parse_coverage_options(slot: &mut CoverageOptions, v: Option<&str>) -> bool {
943+
let Some(v) = v else { return true };
944+
945+
for option in v.split(',') {
946+
let (option, enabled) = match option.strip_prefix("no-") {
947+
Some(without_no) => (without_no, false),
948+
None => (option, true),
949+
};
950+
let slot = match option {
951+
"branch" => &mut slot.branch,
952+
_ => return false,
953+
};
954+
*slot = enabled;
955+
}
956+
957+
true
958+
}
959+
941960
pub(crate) fn parse_instrument_xray(
942961
slot: &mut Option<InstrumentXRay>,
943962
v: Option<&str>,
@@ -1440,11 +1459,9 @@ options! {
14401459
"set the threshold for inlining a function"),
14411460
#[rustc_lint_opt_deny_field_access("use `Session::instrument_coverage` instead of this field")]
14421461
instrument_coverage: InstrumentCoverage = (InstrumentCoverage::No, parse_instrument_coverage, [TRACKED],
1443-
"instrument the generated code to support LLVM source-based code coverage \
1444-
reports (note, the compiler build config must include `profiler = true`); \
1445-
implies `-C symbol-mangling-version=v0`. Optional values are:
1446-
`=no` `=n` `=off` `=false` (default)
1447-
`=yes` `=y` `=on` `=true` (implicit value)"),
1462+
"instrument the generated code to support LLVM source-based code coverage reports \
1463+
(note, the compiler build config must include `profiler = true`); \
1464+
implies `-C symbol-mangling-version=v0`"),
14481465
link_arg: (/* redirected to link_args */) = ((), parse_string_push, [UNTRACKED],
14491466
"a single extra argument to append to the linker invocation (can be used several times)"),
14501467
link_args: Vec<String> = (Vec::new(), parse_list, [UNTRACKED],
@@ -1566,6 +1583,8 @@ options! {
15661583
"set option to collapse debuginfo for macros"),
15671584
combine_cgu: bool = (false, parse_bool, [TRACKED],
15681585
"combine CGUs into a single one"),
1586+
coverage_options: CoverageOptions = (CoverageOptions::default(), parse_coverage_options, [TRACKED],
1587+
"control details of coverage instrumentation"),
15691588
crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
15701589
"inject the given attribute in the crate"),
15711590
cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],

compiler/rustc_session/src/session.rs

+4
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,10 @@ impl Session {
352352
self.opts.cg.instrument_coverage() != InstrumentCoverage::No
353353
}
354354

355+
pub fn instrument_coverage_branch(&self) -> bool {
356+
self.instrument_coverage() && self.opts.unstable_opts.coverage_options.branch
357+
}
358+
355359
pub fn is_sanitizer_cfi_enabled(&self) -> bool {
356360
self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI)
357361
}

src/doc/rustc/src/instrument-coverage.md

+8
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,14 @@ $ llvm-cov report \
346346
more fine-grained coverage options are added.
347347
Using this value is currently not recommended.
348348

349+
## `-Z coverage-options=<options>`
350+
351+
This unstable option provides finer control over some aspects of coverage
352+
instrumentation. Pass one or more of the following values, separated by commas.
353+
354+
- `branch` or `no-branch`
355+
- Placeholder for potential branch coverage support in the future.
356+
349357
## Other references
350358

351359
Rust's implementation and workflow for source-based code coverage is based on the same library and tools used to implement [source-based code coverage in Clang]. (This document is partially based on the Clang guide.)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: incorrect value `bad` for unstable option `coverage-options` - `branch` or `no-branch` was expected
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ needs-profiler-support
2+
//@ revisions: branch no-branch bad
3+
//@ compile-flags -Cinstrument-coverage
4+
5+
//@ [branch] check-pass
6+
//@ [branch] compile-flags: -Zcoverage-options=branch
7+
8+
//@ [no-branch] check-pass
9+
//@ [no-branch] compile-flags: -Zcoverage-options=no-branch
10+
11+
//@ [bad] check-fail
12+
//@ [bad] compile-flags: -Zcoverage-options=bad
13+
14+
fn main() {}

0 commit comments

Comments
 (0)