Skip to content

Commit 6d834a4

Browse files
authored
Rollup merge of rust-lang#76002 - richkadel:llvm-coverage-map-gen-6b.3, r=tmandry
Fix `-Z instrument-coverage` on MSVC Found that `-C link-dead-code` (which was enabled automatically under `-Z instrument-coverage`) was causing the linking error that resulted in segmentation faults in coverage instrumented binaries. Link dead code is now disabled under MSVC, allowing `-Z instrument-coverage` to be enabled under MSVC for the first time. More details are included in Issue rust-lang#76038 . Note this PR makes it possible to support `Z instrument-coverage` but does not enable instrument coverage for MSVC in existing tests. It will be enabled in another PR to follow this one (both PRs coming from original PR rust-lang#75828). r? @tmandry FYI: @wesleywiser
2 parents b675824 + ddb054a commit 6d834a4

File tree

6 files changed

+45
-34
lines changed

6 files changed

+45
-34
lines changed

compiler/rustc_codegen_ssa/src/back/link.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1668,7 +1668,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
16681668
// FIXME: Order dependent, applies to the following objects. Where should it be placed?
16691669
// Try to strip as much out of the generated object by removing unused
16701670
// sections if possible. See more comments in linker.rs
1671-
if sess.opts.cg.link_dead_code != Some(true) {
1671+
if !sess.link_dead_code() {
16721672
let keep_metadata = crate_type == CrateType::Dylib;
16731673
cmd.gc_sections(keep_metadata);
16741674
}

compiler/rustc_middle/src/mir/mono.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ impl<'tcx> MonoItem<'tcx> {
8585
.debugging_opts
8686
.inline_in_all_cgus
8787
.unwrap_or_else(|| tcx.sess.opts.optimize != OptLevel::No)
88-
&& tcx.sess.opts.cg.link_dead_code != Some(true);
88+
&& !tcx.sess.link_dead_code();
8989

9090
match *self {
9191
MonoItem::Fn(ref instance) => {

compiler/rustc_mir/src/monomorphize/partitioning/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ pub fn partition<'tcx>(
190190

191191
// Next we try to make as many symbols "internal" as possible, so LLVM has
192192
// more freedom to optimize.
193-
if tcx.sess.opts.cg.link_dead_code != Some(true) {
193+
if !tcx.sess.link_dead_code() {
194194
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
195195
partitioner.internalize_symbols(tcx, &mut post_inlining, inlining_map);
196196
}
@@ -327,7 +327,7 @@ fn collect_and_partition_mono_items<'tcx>(
327327
}
328328
}
329329
None => {
330-
if tcx.sess.opts.cg.link_dead_code == Some(true) {
330+
if tcx.sess.link_dead_code() {
331331
MonoItemCollectionMode::Eager
332332
} else {
333333
MonoItemCollectionMode::Lazy

compiler/rustc_session/src/config.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -1718,20 +1718,11 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
17181718
);
17191719
}
17201720

1721-
// `-Z instrument-coverage` implies:
1722-
// * `-Z symbol-mangling-version=v0` - to ensure consistent and reversible name mangling.
1723-
// Note, LLVM coverage tools can analyze coverage over multiple runs, including some
1724-
// changes to source code; so mangled names must be consistent across compilations.
1725-
// * `-C link-dead-code` - so unexecuted code is still counted as zero, rather than be
1726-
// optimized out. Note that instrumenting dead code can be explicitly disabled with:
1727-
// `-Z instrument-coverage -C link-dead-code=no`.
1721+
// `-Z instrument-coverage` implies `-Z symbol-mangling-version=v0` - to ensure consistent
1722+
// and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
1723+
// multiple runs, including some changes to source code; so mangled names must be consistent
1724+
// across compilations.
17281725
debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0;
1729-
if cg.link_dead_code == None {
1730-
// FIXME(richkadel): Investigate if the `instrument-coverage` implementation can
1731-
// inject ["zero counters"](https://llvm.org/docs/CoverageMappingFormat.html#counter)
1732-
// in the coverage map when "dead code" is removed, rather than forcing `link-dead-code`.
1733-
cg.link_dead_code = Some(true);
1734-
}
17351726
}
17361727

17371728
if !cg.embed_bitcode {

compiler/rustc_session/src/options.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -885,9 +885,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
885885
"instrument the generated code to support LLVM source-based code coverage \
886886
reports (note, the compiler build config must include `profiler = true`, \
887887
and is mutually exclusive with `-C profile-generate`/`-C profile-use`); \
888-
implies `-C link-dead-code` (unless explicitly disabled)` and \
889-
`-Z symbol-mangling-version=v0`; and disables/overrides some optimization \
890-
options (default: no)"),
888+
implies `-C link-dead-code` (unless targeting MSVC, or explicitly disabled) \
889+
and `-Z symbol-mangling-version=v0`; disables/overrides some Rust \
890+
optimizations (default: no)"),
891891
instrument_mcount: bool = (false, parse_bool, [TRACKED],
892892
"insert function instrument code for mcount-based tracing (default: no)"),
893893
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],

compiler/rustc_session/src/session.rs

+34-14
Original file line numberDiff line numberDiff line change
@@ -1024,6 +1024,40 @@ impl Session {
10241024
|| self.opts.debugging_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::MEMORY)
10251025
}
10261026

1027+
pub fn link_dead_code(&self) -> bool {
1028+
match self.opts.cg.link_dead_code {
1029+
Some(explicitly_set) => explicitly_set,
1030+
None => {
1031+
self.opts.debugging_opts.instrument_coverage
1032+
&& !self.target.target.options.is_like_msvc
1033+
// Issue #76038: (rustc `-Clink-dead-code` causes MSVC linker to produce invalid
1034+
// binaries when LLVM InstrProf counters are enabled). As described by this issue,
1035+
// the "link dead code" option produces incorrect binaries when compiled and linked
1036+
// under MSVC. The resulting Rust programs typically crash with a segmentation
1037+
// fault, or produce an empty "*.profraw" file (profiling counter results normally
1038+
// generated during program exit).
1039+
//
1040+
// If not targeting MSVC, `-Z instrument-coverage` implies `-C link-dead-code`, so
1041+
// unexecuted code is still counted as zero, rather than be optimized out. Note that
1042+
// instrumenting dead code can be explicitly disabled with:
1043+
//
1044+
// `-Z instrument-coverage -C link-dead-code=no`.
1045+
//
1046+
// FIXME(richkadel): Investigate if `instrument-coverage` implementation can inject
1047+
// [zero counters](https://llvm.org/docs/CoverageMappingFormat.html#counter) in the
1048+
// coverage map when "dead code" is removed, rather than forcing `link-dead-code`.
1049+
// This may not be possible, however, if (as it seems to appear) the "dead code"
1050+
// that would otherwise not be linked is only identified as "dead" by the native
1051+
// linker. If that's the case, I believe it is too late for the Rust compiler to
1052+
// leverage any information it might be able to get from the linker regarding what
1053+
// code is dead, to be able to add those counters.
1054+
//
1055+
// On the other hand, if any Rust compiler passes are optimizing out dead code blocks
1056+
// we should inject "zero" counters for those code regions.
1057+
}
1058+
}
1059+
}
1060+
10271061
pub fn mark_attr_known(&self, attr: &Attribute) {
10281062
self.known_attrs.lock().mark(attr)
10291063
}
@@ -1432,20 +1466,6 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
14321466
);
14331467
}
14341468

1435-
// FIXME(richkadel): See `src/test/run-make-fulldeps/instrument-coverage/Makefile`. After
1436-
// compiling with `-Zinstrument-coverage`, the resulting binary generates a segfault during
1437-
// the program's exit process (likely while attempting to generate the coverage stats in
1438-
// the "*.profraw" file). An investigation to resolve the problem on Windows is ongoing,
1439-
// but until this is resolved, the option is disabled on Windows, and the test is skipped
1440-
// when targeting `MSVC`.
1441-
if sess.opts.debugging_opts.instrument_coverage && sess.target.target.options.is_like_msvc {
1442-
sess.warn(
1443-
"Rust source-based code coverage instrumentation (with `-Z instrument-coverage`) \
1444-
is not yet supported on Windows when targeting MSVC. The resulting binaries will \
1445-
still be instrumented for experimentation purposes, but may not execute correctly.",
1446-
);
1447-
}
1448-
14491469
const ASAN_SUPPORTED_TARGETS: &[&str] = &[
14501470
"aarch64-fuchsia",
14511471
"aarch64-unknown-linux-gnu",

0 commit comments

Comments
 (0)