Skip to content

Commit e92ffc3

Browse files
committed
Auto merge of #148993 - RalfJung:miri, r=RalfJung
miri subtree update Subtree update of `miri` to rust-lang/miri@5774cef. Created using https://github.com/rust-lang/josh-sync. r? `@ghost`
2 parents b25b6ea + 725db88 commit e92ffc3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+636
-717
lines changed

src/tools/miri/.github/workflows/ci.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ jobs:
7373
sudo bash -c "echo 'https://ports.ubuntu.com/ priority:4' >> /etc/apt/apt-mirrors.txt"
7474
# Add architecture
7575
sudo dpkg --add-architecture ${{ matrix.multiarch }}
76-
sudo apt update
76+
# Ubuntu Ports often has outdated mirrors so try a few times to get the apt repo
77+
for TRY in $(seq 3); do
78+
{ sudo apt update && break; } || sleep 30
79+
done
7780
# Install needed packages
7881
sudo apt install $(echo "libatomic1: zlib1g-dev:" | sed 's/:/:${{ matrix.multiarch }}/g')
7982
- uses: ./.github/workflows/setup

src/tools/miri/Cargo.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,9 +1519,9 @@ dependencies = [
15191519

15201520
[[package]]
15211521
name = "tikv-jemalloc-sys"
1522-
version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
1522+
version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7"
15231523
source = "registry+https://github.com/rust-lang/crates.io-index"
1524-
checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d"
1524+
checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b"
15251525
dependencies = [
15261526
"cc",
15271527
"libc",

src/tools/miri/README.md

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -464,11 +464,6 @@ to Miri failing to detect cases of undefined behavior in a program.
464464
errors and warnings.
465465
* `-Zmiri-recursive-validation` is a *highly experimental* flag that makes validity checking
466466
recurse below references.
467-
* `-Zmiri-retag-fields[=<all|none|scalar>]` controls when Stacked Borrows retagging recurses into
468-
fields. `all` means it always recurses (the default, and equivalent to `-Zmiri-retag-fields`
469-
without an explicit value), `none` means it never recurses, `scalar` means it only recurses for
470-
types where we would also emit `noalias` annotations in the generated LLVM IR (types passed as
471-
individual scalars or pairs of scalars). Setting this to `none` is **unsound**.
472467
* `-Zmiri-preemption-rate` configures the probability that at the end of a basic block, the active
473468
thread will be preempted. The default is `0.01` (i.e., 1%). Setting this to `0` disables
474469
preemption. Note that even without preemption, the schedule is still non-deterministic:

src/tools/miri/rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8401398e1f14a24670ee1a3203713dc2f0f8b3a8
1+
7a72c5459dd58f81b0e1a0e5436d145485889375

src/tools/miri/src/bin/miri.rs

Lines changed: 67 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,18 @@ extern crate rustc_span;
2323
mod log;
2424

2525
use std::env;
26-
use std::num::NonZero;
26+
use std::num::{NonZero, NonZeroI32};
2727
use std::ops::Range;
2828
use std::rc::Rc;
2929
use std::str::FromStr;
30-
use std::sync::atomic::{AtomicI32, AtomicU32, Ordering};
30+
use std::sync::atomic::{AtomicU32, Ordering};
3131

3232
use miri::{
3333
BacktraceStyle, BorrowTrackerMethod, GenmcConfig, GenmcCtx, MiriConfig, MiriEntryFnType,
34-
ProvenanceMode, RetagFields, TreeBorrowsParams, ValidationMode, run_genmc_mode,
34+
ProvenanceMode, TreeBorrowsParams, ValidationMode, run_genmc_mode,
3535
};
3636
use rustc_abi::ExternAbi;
37-
use rustc_data_structures::sync;
37+
use rustc_data_structures::sync::{self, DynSync};
3838
use rustc_driver::Compilation;
3939
use rustc_hir::def_id::LOCAL_CRATE;
4040
use rustc_hir::{self as hir, Node};
@@ -120,15 +120,47 @@ fn entry_fn(tcx: TyCtxt<'_>) -> (DefId, MiriEntryFnType) {
120120
}
121121
}
122122

123+
fn run_many_seeds(
124+
many_seeds: ManySeedsConfig,
125+
eval_entry_once: impl Fn(u64) -> Result<(), NonZeroI32> + DynSync,
126+
) -> Result<(), NonZeroI32> {
127+
let exit_code =
128+
sync::IntoDynSyncSend(AtomicU32::new(rustc_driver::EXIT_SUCCESS.cast_unsigned()));
129+
let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0));
130+
sync::par_for_each_in(many_seeds.seeds.clone(), |&seed| {
131+
if let Err(return_code) = eval_entry_once(seed.into()) {
132+
eprintln!("FAILING SEED: {seed}");
133+
if !many_seeds.keep_going {
134+
// `abort_if_errors` would unwind but would not actually stop miri, since
135+
// `par_for_each` waits for the rest of the threads to finish.
136+
exit(return_code.get());
137+
}
138+
// Preserve the "maximum" return code (when interpreted as `u32`), to make
139+
// the result order-independent and to make it 0 only if all executions were 0.
140+
exit_code.fetch_max(return_code.get().cast_unsigned(), Ordering::Relaxed);
141+
num_failed.fetch_add(1, Ordering::Relaxed);
142+
}
143+
});
144+
let num_failed = num_failed.0.into_inner();
145+
let exit_code = exit_code.0.into_inner().cast_signed();
146+
if num_failed > 0 {
147+
eprintln!("{num_failed}/{total} SEEDS FAILED", total = many_seeds.seeds.count());
148+
Err(NonZeroI32::new(exit_code).unwrap())
149+
} else {
150+
assert!(exit_code == 0);
151+
Ok(())
152+
}
153+
}
154+
123155
impl rustc_driver::Callbacks for MiriCompilerCalls {
124156
fn after_analysis<'tcx>(
125157
&mut self,
126158
_: &rustc_interface::interface::Compiler,
127159
tcx: TyCtxt<'tcx>,
128160
) -> Compilation {
129-
if tcx.sess.dcx().has_errors_or_delayed_bugs().is_some() {
130-
tcx.dcx().fatal("miri cannot be run on programs that fail compilation");
131-
}
161+
tcx.dcx().abort_if_errors();
162+
tcx.dcx().flush_delayed();
163+
132164
if !tcx.crate_types().contains(&CrateType::Executable) {
133165
tcx.dcx().fatal("miri only makes sense on bin crates");
134166
}
@@ -161,64 +193,28 @@ impl rustc_driver::Callbacks for MiriCompilerCalls {
161193
optimizations is usually marginal at best.");
162194
}
163195

164-
// Run in GenMC mode if enabled.
165-
if config.genmc_config.is_some() {
166-
// Validate GenMC settings.
167-
if let Err(err) = GenmcConfig::validate(&mut config, tcx) {
168-
fatal_error!("Invalid settings: {err}");
169-
}
170-
171-
// This is the entry point used in GenMC mode.
172-
// This closure will be called multiple times to explore the concurrent execution space of the program.
173-
let eval_entry_once = |genmc_ctx: Rc<GenmcCtx>| {
196+
let res = if config.genmc_config.is_some() {
197+
assert!(self.many_seeds.is_none());
198+
run_genmc_mode(tcx, &config, |genmc_ctx: Rc<GenmcCtx>| {
174199
miri::eval_entry(tcx, entry_def_id, entry_type, &config, Some(genmc_ctx))
175-
};
176-
let return_code = run_genmc_mode(&config, eval_entry_once, tcx).unwrap_or_else(|| {
177-
tcx.dcx().abort_if_errors();
178-
rustc_driver::EXIT_FAILURE
179-
});
180-
exit(return_code);
181-
};
182-
183-
if let Some(many_seeds) = self.many_seeds.take() {
200+
})
201+
} else if let Some(many_seeds) = self.many_seeds.take() {
184202
assert!(config.seed.is_none());
185-
let exit_code = sync::IntoDynSyncSend(AtomicI32::new(rustc_driver::EXIT_SUCCESS));
186-
let num_failed = sync::IntoDynSyncSend(AtomicU32::new(0));
187-
sync::par_for_each_in(many_seeds.seeds.clone(), |seed| {
203+
run_many_seeds(many_seeds, |seed| {
188204
let mut config = config.clone();
189-
config.seed = Some((*seed).into());
205+
config.seed = Some(seed);
190206
eprintln!("Trying seed: {seed}");
191-
let return_code = miri::eval_entry(
192-
tcx,
193-
entry_def_id,
194-
entry_type,
195-
&config,
196-
/* genmc_ctx */ None,
197-
)
198-
.unwrap_or(rustc_driver::EXIT_FAILURE);
199-
if return_code != rustc_driver::EXIT_SUCCESS {
200-
eprintln!("FAILING SEED: {seed}");
201-
if !many_seeds.keep_going {
202-
// `abort_if_errors` would actually not stop, since `par_for_each` waits for the
203-
// rest of the to finish, so we just exit immediately.
204-
exit(return_code);
205-
}
206-
exit_code.store(return_code, Ordering::Relaxed);
207-
num_failed.fetch_add(1, Ordering::Relaxed);
208-
}
209-
});
210-
let num_failed = num_failed.0.into_inner();
211-
if num_failed > 0 {
212-
eprintln!("{num_failed}/{total} SEEDS FAILED", total = many_seeds.seeds.count());
213-
}
214-
exit(exit_code.0.into_inner());
207+
miri::eval_entry(tcx, entry_def_id, entry_type, &config, /* genmc_ctx */ None)
208+
})
215209
} else {
216-
let return_code = miri::eval_entry(tcx, entry_def_id, entry_type, &config, None)
217-
.unwrap_or_else(|| {
218-
tcx.dcx().abort_if_errors();
219-
rustc_driver::EXIT_FAILURE
220-
});
221-
exit(return_code);
210+
miri::eval_entry(tcx, entry_def_id, entry_type, &config, None)
211+
};
212+
213+
if let Err(return_code) = res {
214+
tcx.dcx().abort_if_errors();
215+
exit(return_code.get());
216+
} else {
217+
exit(rustc_driver::EXIT_SUCCESS);
222218
}
223219

224220
// Unreachable.
@@ -571,21 +567,17 @@ fn main() {
571567
} else if arg == "-Zmiri-mute-stdout-stderr" {
572568
miri_config.mute_stdout_stderr = true;
573569
} else if arg == "-Zmiri-retag-fields" {
574-
miri_config.retag_fields = RetagFields::Yes;
570+
eprintln!(
571+
"warning: `-Zmiri-retag-fields` is a NOP and will be removed in a future version of Miri.\n\
572+
Field retagging has been on-by-default for a long time."
573+
);
575574
} else if arg == "-Zmiri-fixed-schedule" {
576575
miri_config.fixed_scheduling = true;
577576
} else if arg == "-Zmiri-deterministic-concurrency" {
578577
miri_config.fixed_scheduling = true;
579578
miri_config.address_reuse_cross_thread_rate = 0.0;
580579
miri_config.cmpxchg_weak_failure_rate = 0.0;
581580
miri_config.weak_memory_emulation = false;
582-
} else if let Some(retag_fields) = arg.strip_prefix("-Zmiri-retag-fields=") {
583-
miri_config.retag_fields = match retag_fields {
584-
"all" => RetagFields::Yes,
585-
"none" => RetagFields::No,
586-
"scalar" => RetagFields::OnlyScalar,
587-
_ => fatal_error!("`-Zmiri-retag-fields` can only be `all`, `none`, or `scalar`"),
588-
};
589581
} else if let Some(param) = arg.strip_prefix("-Zmiri-seed=") {
590582
let seed = param.parse::<u64>().unwrap_or_else(|_| {
591583
fatal_error!("-Zmiri-seed must be an integer that fits into u64")
@@ -747,6 +739,13 @@ fn main() {
747739
);
748740
};
749741

742+
// Validate GenMC settings.
743+
if miri_config.genmc_config.is_some()
744+
&& let Err(err) = GenmcConfig::validate(&mut miri_config)
745+
{
746+
fatal_error!("Invalid settings: {err}");
747+
}
748+
750749
debug!("rustc arguments: {:?}", rustc_args);
751750
debug!("crate arguments: {:?}", miri_config.args);
752751
if !miri_config.native_lib.is_empty() && miri_config.native_lib_enable_tracing {

src/tools/miri/src/borrow_tracker/mod.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@ pub struct GlobalStateInner {
116116
protected_tags: FxHashMap<BorTag, ProtectorKind>,
117117
/// The pointer ids to trace
118118
tracked_pointer_tags: FxHashSet<BorTag>,
119-
/// Whether to recurse into datatypes when searching for pointers to retag.
120-
retag_fields: RetagFields,
121119
}
122120

123121
impl VisitProvenance for GlobalStateInner {
@@ -131,18 +129,6 @@ impl VisitProvenance for GlobalStateInner {
131129
/// We need interior mutable access to the global state.
132130
pub type GlobalState = RefCell<GlobalStateInner>;
133131

134-
/// Policy on whether to recurse into fields to retag
135-
#[derive(Copy, Clone, Debug)]
136-
pub enum RetagFields {
137-
/// Don't retag any fields.
138-
No,
139-
/// Retag all fields.
140-
Yes,
141-
/// Only retag fields of types with Scalar and ScalarPair layout,
142-
/// to match the LLVM `noalias` we generate.
143-
OnlyScalar,
144-
}
145-
146132
/// The flavor of the protector.
147133
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
148134
pub enum ProtectorKind {
@@ -168,15 +154,13 @@ impl GlobalStateInner {
168154
pub fn new(
169155
borrow_tracker_method: BorrowTrackerMethod,
170156
tracked_pointer_tags: FxHashSet<BorTag>,
171-
retag_fields: RetagFields,
172157
) -> Self {
173158
GlobalStateInner {
174159
borrow_tracker_method,
175160
next_ptr_tag: BorTag::one(),
176161
root_ptr_tags: FxHashMap::default(),
177162
protected_tags: FxHashMap::default(),
178163
tracked_pointer_tags,
179-
retag_fields,
180164
}
181165
}
182166

@@ -244,11 +228,7 @@ pub struct TreeBorrowsParams {
244228

245229
impl BorrowTrackerMethod {
246230
pub fn instantiate_global_state(self, config: &MiriConfig) -> GlobalState {
247-
RefCell::new(GlobalStateInner::new(
248-
self,
249-
config.tracked_pointer_tags.clone(),
250-
config.retag_fields,
251-
))
231+
RefCell::new(GlobalStateInner::new(self, config.tracked_pointer_tags.clone()))
252232
}
253233

254234
pub fn get_tree_borrows_params(self) -> TreeBorrowsParams {

src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs

Lines changed: 6 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::fmt::Write;
99
use std::sync::atomic::AtomicBool;
1010
use std::{cmp, mem};
1111

12-
use rustc_abi::{BackendRepr, Size};
12+
use rustc_abi::Size;
1313
use rustc_data_structures::fx::FxHashSet;
1414
use rustc_middle::mir::{Mutability, RetagKind};
1515
use rustc_middle::ty::layout::HasTypingEnv;
@@ -887,22 +887,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
887887
place: &PlaceTy<'tcx>,
888888
) -> InterpResult<'tcx> {
889889
let this = self.eval_context_mut();
890-
let retag_fields = this.machine.borrow_tracker.as_mut().unwrap().get_mut().retag_fields;
891890
let retag_cause = match kind {
892891
RetagKind::TwoPhase => unreachable!(), // can only happen in `retag_ptr_value`
893892
RetagKind::FnEntry => RetagCause::FnEntry,
894893
RetagKind::Default | RetagKind::Raw => RetagCause::Normal,
895894
};
896-
let mut visitor =
897-
RetagVisitor { ecx: this, kind, retag_cause, retag_fields, in_field: false };
895+
let mut visitor = RetagVisitor { ecx: this, kind, retag_cause, in_field: false };
898896
return visitor.visit_value(place);
899897

900898
// The actual visitor.
901899
struct RetagVisitor<'ecx, 'tcx> {
902900
ecx: &'ecx mut MiriInterpCx<'tcx>,
903901
kind: RetagKind,
904902
retag_cause: RetagCause,
905-
retag_fields: RetagFields,
906903
in_field: bool,
907904
}
908905
impl<'ecx, 'tcx> RetagVisitor<'ecx, 'tcx> {
@@ -967,24 +964,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
967964
self.walk_value(place)?;
968965
}
969966
_ => {
970-
// Not a reference/pointer/box. Only recurse if configured appropriately.
971-
let recurse = match self.retag_fields {
972-
RetagFields::No => false,
973-
RetagFields::Yes => true,
974-
RetagFields::OnlyScalar => {
975-
// Matching `ArgAbi::new` at the time of writing, only fields of
976-
// `Scalar` and `ScalarPair` ABI are considered.
977-
matches!(
978-
place.layout.backend_repr,
979-
BackendRepr::Scalar(..) | BackendRepr::ScalarPair(..)
980-
)
981-
}
982-
};
983-
if recurse {
984-
let in_field = mem::replace(&mut self.in_field, true); // remember and restore old value
985-
self.walk_value(place)?;
986-
self.in_field = in_field;
987-
}
967+
// Not a reference/pointer/box. Recurse.
968+
let in_field = mem::replace(&mut self.in_field, true); // remember and restore old value
969+
self.walk_value(place)?;
970+
self.in_field = in_field;
988971
}
989972
}
990973

0 commit comments

Comments
 (0)