Skip to content

Commit 4f550f1

Browse files
committed
Improve warnings on incompatible options involving -Zinstrument-coverage
Adds checks for: * `no_core` attribute * explicitly-enabled `legacy` symbol mangling * mir_opt_level > 1 (which enables inlining) I removed code from the `Inline` MIR pass that forcibly disabled inlining if `-Zinstrument-coverage` was set. The default `mir_opt_level` does not enable inlining anyway. But if the level is explicitly set and is greater than 1, I issue a warning. The new warnings show up in tests, which is much better for diagnosing potential option conflicts in these cases.
1 parent eb963ff commit 4f550f1

File tree

16 files changed

+103
-49
lines changed

16 files changed

+103
-49
lines changed

compiler/rustc_interface/src/tests.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -561,7 +561,7 @@ fn test_debugging_options_tracking_hash() {
561561
tracked!(link_only, true);
562562
tracked!(merge_functions, Some(MergeFunctions::Disabled));
563563
tracked!(mir_emit_retag, true);
564-
tracked!(mir_opt_level, 3);
564+
tracked!(mir_opt_level, Some(3));
565565
tracked!(mutable_noalias, true);
566566
tracked!(new_llvm_pass_manager, true);
567567
tracked!(no_codegen, true);
@@ -587,7 +587,7 @@ fn test_debugging_options_tracking_hash() {
587587
tracked!(share_generics, Some(true));
588588
tracked!(show_span, Some(String::from("abc")));
589589
tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1));
590-
tracked!(symbol_mangling_version, SymbolManglingVersion::V0);
590+
tracked!(symbol_mangling_version, Some(SymbolManglingVersion::V0));
591591
tracked!(teach, true);
592592
tracked!(thinlto, Some(true));
593593
tracked!(tune_cpu, Some(String::from("abc")));

compiler/rustc_metadata/src/creader.rs

+9-2
Original file line numberDiff line numberDiff line change
@@ -706,14 +706,21 @@ impl<'a> CrateLoader<'a> {
706706
self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime());
707707
}
708708

709-
fn inject_profiler_runtime(&mut self) {
709+
fn inject_profiler_runtime(&mut self, krate: &ast::Crate) {
710710
if (self.sess.opts.debugging_opts.instrument_coverage
711711
|| self.sess.opts.debugging_opts.profile
712712
|| self.sess.opts.cg.profile_generate.enabled())
713713
&& !self.sess.opts.debugging_opts.no_profiler_runtime
714714
{
715715
info!("loading profiler");
716716

717+
if self.sess.contains_name(&krate.attrs, sym::no_core) {
718+
self.sess.err(
719+
"`profiler_builtins` crate (required by compiler options) \
720+
is not compatible with crate attribute `#![no_core]`",
721+
);
722+
}
723+
717724
let name = sym::profiler_builtins;
718725
let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None);
719726
let data = self.cstore.get_crate_data(cnum);
@@ -879,7 +886,7 @@ impl<'a> CrateLoader<'a> {
879886
}
880887

881888
pub fn postprocess(&mut self, krate: &ast::Crate) {
882-
self.inject_profiler_runtime();
889+
self.inject_profiler_runtime(krate);
883890
self.inject_allocator_crate(krate);
884891
self.inject_panic_runtime(krate);
885892

compiler/rustc_metadata/src/rmeta/encoder.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,12 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
663663
no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
664664
panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
665665
profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
666-
symbol_mangling_version: tcx.sess.opts.debugging_opts.symbol_mangling_version,
666+
symbol_mangling_version: tcx
667+
.sess
668+
.opts
669+
.debugging_opts
670+
.symbol_mangling_version
671+
.unwrap_or(SymbolManglingVersion::default()),
667672

668673
crate_deps,
669674
dylib_dependency_formats,

compiler/rustc_mir/src/transform/const_prop.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_middle::ty::subst::{InternalSubsts, Subst};
2222
use rustc_middle::ty::{
2323
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeFoldable,
2424
};
25+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
2526
use rustc_session::lint;
2627
use rustc_span::{def_id::DefId, Span};
2728
use rustc_target::abi::{HasDataLayout, LayoutOf, Size, TargetDataLayout};
@@ -708,7 +709,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
708709
return None;
709710
}
710711

711-
if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 3 {
712+
if self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) >= 3 {
712713
self.eval_rvalue_with_identities(rvalue, place)
713714
} else {
714715
self.use_ecx(|this| this.ecx.eval_rvalue_into_place(rvalue, place))
@@ -886,7 +887,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
886887

887888
/// Returns `true` if and only if this `op` should be const-propagated into.
888889
fn should_const_prop(&mut self, op: OpTy<'tcx>) -> bool {
889-
let mir_opt_level = self.tcx.sess.opts.debugging_opts.mir_opt_level;
890+
let mir_opt_level =
891+
self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT);
890892

891893
if mir_opt_level == 0 {
892894
return false;
@@ -1056,7 +1058,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
10561058

10571059
// Only const prop copies and moves on `mir_opt_level=2` as doing so
10581060
// currently slightly increases compile time in some cases.
1059-
if self.tcx.sess.opts.debugging_opts.mir_opt_level >= 2 {
1061+
if self.tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) >= 2 {
10601062
self.propagate_operand(operand)
10611063
}
10621064
}

compiler/rustc_mir/src/transform/dest_prop.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ use rustc_middle::mir::{
115115
Rvalue, Statement, StatementKind, Terminator, TerminatorKind,
116116
};
117117
use rustc_middle::ty::{self, Ty, TyCtxt};
118+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
118119

119120
// Empirical measurements have resulted in some observations:
120121
// - Running on a body with a single block and 500 locals takes barely any time
@@ -129,7 +130,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation {
129130
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
130131
// Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove
131132
// storage statements at the moment).
132-
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
133+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) <= 1 {
133134
return;
134135
}
135136

compiler/rustc_mir/src/transform/early_otherwise_branch.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::{transform::MirPass, util::patch::MirPatch};
22
use rustc_middle::mir::*;
33
use rustc_middle::ty::{Ty, TyCtxt};
4+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
45
use std::fmt::Debug;
56

67
use super::simplify::simplify_cfg;
@@ -26,7 +27,7 @@ pub struct EarlyOtherwiseBranch;
2627

2728
impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch {
2829
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
29-
if tcx.sess.opts.debugging_opts.mir_opt_level < 2 {
30+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 2 {
3031
return;
3132
}
3233
trace!("running EarlyOtherwiseBranch on {:?}", body.source);

compiler/rustc_mir/src/transform/inline.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::mir::visit::*;
99
use rustc_middle::mir::*;
1010
use rustc_middle::ty::subst::Subst;
1111
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
12+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
1213
use rustc_span::{hygiene::ExpnKind, ExpnData, Span};
1314
use rustc_target::spec::abi::Abi;
1415

@@ -37,15 +38,7 @@ struct CallSite<'tcx> {
3738

3839
impl<'tcx> MirPass<'tcx> for Inline {
3940
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
40-
if tcx.sess.opts.debugging_opts.mir_opt_level < 2 {
41-
return;
42-
}
43-
44-
if tcx.sess.opts.debugging_opts.instrument_coverage {
45-
// The current implementation of source code coverage injects code region counters
46-
// into the MIR, and assumes a 1-to-1 correspondence between MIR and source-code-
47-
// based function.
48-
debug!("function inlining is disabled when compiling with `instrument_coverage`");
41+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 2 {
4942
return;
5043
}
5144

compiler/rustc_mir/src/transform/match_branches.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::transform::MirPass;
22
use rustc_middle::mir::*;
33
use rustc_middle::ty::TyCtxt;
4+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
45

56
pub struct MatchBranchSimplification;
67

@@ -38,7 +39,7 @@ pub struct MatchBranchSimplification;
3839
3940
impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
4041
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
41-
if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 {
42+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) <= 1 {
4243
return;
4344
}
4445

compiler/rustc_mir/src/transform/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_middle::mir::visit::Visitor as _;
1010
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
1111
use rustc_middle::ty::query::Providers;
1212
use rustc_middle::ty::{self, TyCtxt, TypeFoldable};
13+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
1314
use rustc_span::{Span, Symbol};
1415
use std::borrow::Cow;
1516

@@ -373,7 +374,7 @@ fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tc
373374
}
374375

375376
fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
376-
let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level;
377+
let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT);
377378

378379
// Lowering generator control-flow and variables has to happen before we do anything else
379380
// to them. We run some optimizations before that, because they may be harder to do on the state

compiler/rustc_mir/src/transform/multiple_return_terminators.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@ use crate::transform::{simplify, MirPass};
55
use rustc_index::bit_set::BitSet;
66
use rustc_middle::mir::*;
77
use rustc_middle::ty::TyCtxt;
8+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
89

910
pub struct MultipleReturnTerminators;
1011

1112
impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators {
1213
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
13-
if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
14+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 3 {
1415
return;
1516
}
1617

compiler/rustc_mir/src/transform/nrvo.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_index::bit_set::HybridBitSet;
55
use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor};
66
use rustc_middle::mir::{self, BasicBlock, Local, Location};
77
use rustc_middle::ty::TyCtxt;
8+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
89

910
use crate::transform::MirPass;
1011

@@ -34,7 +35,7 @@ pub struct RenameReturnPlace;
3435

3536
impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
3637
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
37-
if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
38+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) == 0 {
3839
return;
3940
}
4041

compiler/rustc_mir/src/transform/unreachable_prop.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ use crate::transform::MirPass;
77
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
88
use rustc_middle::mir::*;
99
use rustc_middle::ty::TyCtxt;
10+
use rustc_session::config::MIR_OPT_LEVEL_DEFAULT;
1011

1112
pub struct UnreachablePropagation;
1213

1314
impl MirPass<'_> for UnreachablePropagation {
1415
fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
15-
if tcx.sess.opts.debugging_opts.mir_opt_level < 3 {
16+
if tcx.sess.opts.debugging_opts.mir_opt_level.unwrap_or(MIR_OPT_LEVEL_DEFAULT) < 3 {
1617
// Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt
1718
// perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
1819
return;

compiler/rustc_session/src/config.rs

+36-2
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ pub enum MirSpanview {
174174
Block,
175175
}
176176

177+
pub const MIR_OPT_LEVEL_DEFAULT: usize = 1;
178+
177179
#[derive(Clone, PartialEq, Hash)]
178180
pub enum LinkerPluginLto {
179181
LinkerPlugin(PathBuf),
@@ -212,6 +214,12 @@ pub enum SymbolManglingVersion {
212214
V0,
213215
}
214216

217+
impl SymbolManglingVersion {
218+
pub fn default() -> Self {
219+
SymbolManglingVersion::Legacy
220+
}
221+
}
222+
215223
impl_stable_hash_via_hash!(SymbolManglingVersion);
216224

217225
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
@@ -1757,7 +1765,33 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
17571765
// and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
17581766
// multiple runs, including some changes to source code; so mangled names must be consistent
17591767
// across compilations.
1760-
debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0;
1768+
match debugging_opts.symbol_mangling_version {
1769+
None => {
1770+
debugging_opts.symbol_mangling_version = Some(SymbolManglingVersion::V0);
1771+
}
1772+
Some(SymbolManglingVersion::Legacy) => {
1773+
early_warn(
1774+
error_format,
1775+
"-Z instrument-coverage requires symbol mangling version `v0`, \
1776+
but `-Z symbol-mangling-version=legacy` was specified",
1777+
);
1778+
}
1779+
Some(SymbolManglingVersion::V0) => {}
1780+
}
1781+
1782+
match debugging_opts.mir_opt_level {
1783+
Some(level) if level > 1 => {
1784+
early_warn(
1785+
error_format,
1786+
&format!(
1787+
"`-Z mir-opt-level={}` (any level > 1) enables function inlining, which \
1788+
limits the effectiveness of `-Z instrument-coverage`.",
1789+
level,
1790+
),
1791+
);
1792+
}
1793+
_ => {}
1794+
}
17611795
}
17621796

17631797
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
@@ -2162,7 +2196,7 @@ crate mod dep_tracking {
21622196
impl_dep_tracking_hash_via_hash!(Edition);
21632197
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
21642198
impl_dep_tracking_hash_via_hash!(SwitchWithOptPath);
2165-
impl_dep_tracking_hash_via_hash!(SymbolManglingVersion);
2199+
impl_dep_tracking_hash_via_hash!(Option<SymbolManglingVersion>);
21662200
impl_dep_tracking_hash_via_hash!(Option<SourceFileHashAlgorithm>);
21672201
impl_dep_tracking_hash_via_hash!(TrimmedDefPaths);
21682202

compiler/rustc_session/src/options.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -677,12 +677,12 @@ macro_rules! options {
677677
}
678678

679679
fn parse_symbol_mangling_version(
680-
slot: &mut SymbolManglingVersion,
680+
slot: &mut Option<SymbolManglingVersion>,
681681
v: Option<&str>,
682682
) -> bool {
683683
*slot = match v {
684-
Some("legacy") => SymbolManglingVersion::Legacy,
685-
Some("v0") => SymbolManglingVersion::V0,
684+
Some("legacy") => Some(SymbolManglingVersion::Legacy),
685+
Some("v0") => Some(SymbolManglingVersion::V0),
686686
_ => return false,
687687
};
688688
true
@@ -970,7 +970,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
970970
mir_emit_retag: bool = (false, parse_bool, [TRACKED],
971971
"emit Retagging MIR statements, interpreted e.g., by miri; implies -Zmir-opt-level=0 \
972972
(default: no)"),
973-
mir_opt_level: usize = (1, parse_uint, [TRACKED],
973+
mir_opt_level: Option<usize> = (None, parse_opt_uint, [TRACKED],
974974
"MIR optimization level (0-3; default: 1)"),
975975
mutable_noalias: bool = (false, parse_bool, [TRACKED],
976976
"emit noalias metadata for mutable references (default: no)"),
@@ -1088,9 +1088,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
10881088
"hash algorithm of source files in debug info (`md5`, `sha1`, or `sha256`)"),
10891089
strip: Strip = (Strip::None, parse_strip, [UNTRACKED],
10901090
"tell the linker which information to strip (`none` (default), `debuginfo` or `symbols`)"),
1091-
symbol_mangling_version: SymbolManglingVersion = (SymbolManglingVersion::Legacy,
1091+
symbol_mangling_version: Option<SymbolManglingVersion> = (None,
10921092
parse_symbol_mangling_version, [TRACKED],
1093-
"which mangling version to use for symbol names"),
1093+
"which mangling version to use for symbol names ('legacy' (default) or 'v0')"),
10941094
teach: bool = (false, parse_bool, [TRACKED],
10951095
"show extended diagnostic help (default: no)"),
10961096
terminal_width: Option<usize> = (None, parse_opt_uint, [UNTRACKED],

compiler/rustc_symbol_mangling/src/lib.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,11 @@ fn compute_symbol_name(
245245
// 2. we favor `instantiating_crate` where possible (i.e. when `Some`)
246246
let mangling_version_crate = instantiating_crate.unwrap_or(def_id.krate);
247247
let mangling_version = if mangling_version_crate == LOCAL_CRATE {
248-
tcx.sess.opts.debugging_opts.symbol_mangling_version
248+
tcx.sess
249+
.opts
250+
.debugging_opts
251+
.symbol_mangling_version
252+
.unwrap_or(SymbolManglingVersion::default())
249253
} else {
250254
tcx.symbol_mangling_version(mangling_version_crate)
251255
};

0 commit comments

Comments
 (0)