From 4784f0d3f8502fa3c19123c219e1049ae963c983 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 21 Sep 2022 17:55:10 +0200 Subject: [PATCH 01/28] readme: tag-gc tweaks --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1f4c52d5b8507..2e27bb39afd0f 100644 --- a/README.md +++ b/README.md @@ -324,10 +324,6 @@ environment variable. We first document the most relevant and most commonly used ensure alignment. (The standard library `align_to` method works fine in both modes; under symbolic alignment it only fills the middle slice when the allocation guarantees sufficient alignment.) -* `-Zmiri-tag-gc=` configures how often the pointer tag garbage collector runs. The default - is to search for and remove unreachable tags once every `10,000` basic blocks. Setting this to - `0` disables the garbage collector, which causes some programs to have explosive memory usage - and/or super-linear runtime. The remaining flags are for advanced use only, and more likely to change or be removed. Some of these are **unsound**, which means they can lead @@ -378,6 +374,10 @@ to Miri failing to detect cases of undefined behavior in a program. * `-Zmiri-retag-fields` changes Stacked Borrows retagging to recurse into fields. This means that references in fields of structs/enums/tuples/arrays/... are retagged, and in particular, they are protected when passed as function arguments. +* `-Zmiri-tag-gc=` configures how often the pointer tag garbage collector runs. The default + is to search for and remove unreachable tags once every `10000` basic blocks. Setting this to + `0` disables the garbage collector, which causes some programs to have explosive memory usage + and/or super-linear runtime. * `-Zmiri-track-alloc-id=,,...` shows a backtrace when the given allocations are being allocated or freed. This helps in debugging memory leaks and use after free bugs. Specifying this argument multiple times does not overwrite the previous From 42f64f74162ccda4ed388de2ed8f9384983ddc5d Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 8 Sep 2022 19:16:50 -0400 Subject: [PATCH 02/28] Don't move too far down the call stack when reporting FnEntry diagnostics --- src/helpers.rs | 26 +++++++++-------- src/stacked_borrows/diagnostics.rs | 4 +-- .../fail/stacked_borrows/aliasing_mut3.stderr | 2 +- .../fnentry_invalidation.stderr | 2 +- .../stacked_borrows/fnentry_invalidation2.rs | 21 ++++++++++++++ .../fnentry_invalidation2.stderr | 28 +++++++++++++++++++ 6 files changed, 67 insertions(+), 16 deletions(-) create mode 100644 tests/fail/stacked_borrows/fnentry_invalidation2.rs create mode 100644 tests/fail/stacked_borrows/fnentry_invalidation2.stderr diff --git a/src/helpers.rs b/src/helpers.rs index 0f0bfa355bdc7..15833fe42adc9 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,5 +1,6 @@ pub mod convert; +use std::cmp; use std::mem; use std::num::NonZeroUsize; use std::time::Duration; @@ -908,24 +909,25 @@ impl<'a, 'mir: 'a, 'tcx: 'a + 'mir> CurrentSpan<'a, 'mir, 'tcx> { /// This function is backed by a cache, and can be assumed to be very fast. pub fn get(&mut self) -> Span { let idx = self.current_frame_idx(); - Self::frame_span(self.machine, idx) + self.stack().get(idx).map(Frame::current_span).unwrap_or(rustc_span::DUMMY_SP) } - /// Similar to `CurrentSpan::get`, but retrieves the parent frame of the first non-local frame. + /// Returns the span of the *caller* of the current operation, again + /// walking down the stack to find the closest frame in a local crate, if the caller of the + /// current operation is not in a local crate. /// This is useful when we are processing something which occurs on function-entry and we want /// to point at the call to the function, not the function definition generally. - pub fn get_parent(&mut self) -> Span { - let idx = self.current_frame_idx(); - Self::frame_span(self.machine, idx.wrapping_sub(1)) + pub fn get_caller(&mut self) -> Span { + // We need to go down at least to the caller (len - 2), or however + // far we have to go to find a frame in a local crate. + let local_frame_idx = self.current_frame_idx(); + let stack = self.stack(); + let idx = cmp::min(local_frame_idx, stack.len().saturating_sub(2)); + stack.get(idx).map(Frame::current_span).unwrap_or(rustc_span::DUMMY_SP) } - fn frame_span(machine: &MiriMachine<'_, '_>, idx: usize) -> Span { - machine - .threads - .active_thread_stack() - .get(idx) - .map(Frame::current_span) - .unwrap_or(rustc_span::DUMMY_SP) + fn stack(&self) -> &[Frame<'mir, 'tcx, Provenance, machine::FrameData<'tcx>>] { + self.machine.threads.active_thread_stack() } fn current_frame_idx(&mut self) -> usize { diff --git a/src/stacked_borrows/diagnostics.rs b/src/stacked_borrows/diagnostics.rs index 0d76ed4e30878..8deb8cda2e179 100644 --- a/src/stacked_borrows/diagnostics.rs +++ b/src/stacked_borrows/diagnostics.rs @@ -82,7 +82,7 @@ impl fmt::Display for InvalidationCause { InvalidationCause::Access(kind) => write!(f, "{}", kind), InvalidationCause::Retag(perm, kind) => if *kind == RetagCause::FnEntry { - write!(f, "{:?} FnEntry retag", perm) + write!(f, "{:?} FnEntry retag inside this call", perm) } else { write!(f, "{:?} retag", perm) }, @@ -275,7 +275,7 @@ impl<'span, 'history, 'ecx, 'mir, 'tcx> DiagnosticCx<'span, 'history, 'ecx, 'mir let (range, cause) = match &self.operation { Operation::Retag(RetagOp { cause, range, permission, .. }) => { if *cause == RetagCause::FnEntry { - span = self.current_span.get_parent(); + span = self.current_span.get_caller(); } (*range, InvalidationCause::Retag(permission.unwrap(), *cause)) } diff --git a/tests/fail/stacked_borrows/aliasing_mut3.stderr b/tests/fail/stacked_borrows/aliasing_mut3.stderr index c2ea90f242a22..eb6b01fc6b12b 100644 --- a/tests/fail/stacked_borrows/aliasing_mut3.stderr +++ b/tests/fail/stacked_borrows/aliasing_mut3.stderr @@ -14,7 +14,7 @@ help: was created by a SharedReadOnly retag at offsets [0x0..0x4] | LL | safe_raw(xraw, xshr); | ^^^^ -help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag +help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call --> $DIR/aliasing_mut3.rs:LL:CC | LL | safe_raw(xraw, xshr); diff --git a/tests/fail/stacked_borrows/fnentry_invalidation.stderr b/tests/fail/stacked_borrows/fnentry_invalidation.stderr index 653ceca858859..e81411bbdd86c 100644 --- a/tests/fail/stacked_borrows/fnentry_invalidation.stderr +++ b/tests/fail/stacked_borrows/fnentry_invalidation.stderr @@ -14,7 +14,7 @@ help: was created by a SharedReadWrite retag at offsets [0x0..0x4] | LL | let z = &mut x as *mut i32; | ^^^^^^ -help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag +help: was later invalidated at offsets [0x0..0x4] by a Unique FnEntry retag inside this call --> $DIR/fnentry_invalidation.rs:LL:CC | LL | x.do_bad(); diff --git a/tests/fail/stacked_borrows/fnentry_invalidation2.rs b/tests/fail/stacked_borrows/fnentry_invalidation2.rs new file mode 100644 index 0000000000000..dc51a8a8ac6c7 --- /dev/null +++ b/tests/fail/stacked_borrows/fnentry_invalidation2.rs @@ -0,0 +1,21 @@ +// Regression test for https://github.com/rust-lang/miri/issues/2536 +// This tests that we don't try to back too far up the stack when selecting a span to report. +// We should display the as_mut_ptr() call as the location of the invalidation, not the call to +// inner + +struct Thing<'a> { + sli: &'a mut [i32], +} + +fn main() { + let mut t = Thing { sli: &mut [0, 1, 2] }; + let ptr = t.sli.as_ptr(); + inner(&mut t); + unsafe { + let _oof = *ptr; //~ ERROR: /read access .* tag does not exist in the borrow stack/ + } +} + +fn inner(t: &mut Thing) { + let _ = t.sli.as_mut_ptr(); +} diff --git a/tests/fail/stacked_borrows/fnentry_invalidation2.stderr b/tests/fail/stacked_borrows/fnentry_invalidation2.stderr new file mode 100644 index 0000000000000..d6d0084fa2a77 --- /dev/null +++ b/tests/fail/stacked_borrows/fnentry_invalidation2.stderr @@ -0,0 +1,28 @@ +error: Undefined Behavior: attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + --> $DIR/fnentry_invalidation2.rs:LL:CC + | +LL | let _oof = *ptr; + | ^^^^ + | | + | attempting a read access using at ALLOC[0x0], but that tag does not exist in the borrow stack for this location + | this error occurs as part of an access at ALLOC[0x0..0x4] + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information +help: was created by a SharedReadOnly retag at offsets [0x0..0xc] + --> $DIR/fnentry_invalidation2.rs:LL:CC + | +LL | let ptr = t.sli.as_ptr(); + | ^^^^^^^^^^^^^^ +help: was later invalidated at offsets [0x0..0xc] by a Unique FnEntry retag inside this call + --> $DIR/fnentry_invalidation2.rs:LL:CC + | +LL | let _ = t.sli.as_mut_ptr(); + | ^^^^^^^^^^^^^^^^^^ + = note: BACKTRACE: + = note: inside `main` at $DIR/fnentry_invalidation2.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + From fdc7dc3bae8604f29621d5aae36febecccf58643 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 22 Sep 2022 10:44:03 -0400 Subject: [PATCH 03/28] Only add 'inside this call' for Invalidation diagnostics --- src/stacked_borrows/diagnostics.rs | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/stacked_borrows/diagnostics.rs b/src/stacked_borrows/diagnostics.rs index 8deb8cda2e179..2cc7a88704ea3 100644 --- a/src/stacked_borrows/diagnostics.rs +++ b/src/stacked_borrows/diagnostics.rs @@ -66,13 +66,20 @@ enum InvalidationCause { impl Invalidation { fn generate_diagnostic(&self) -> (String, SpanData) { - ( + let message = if let InvalidationCause::Retag(_, RetagCause::FnEntry) = self.cause { + // For a FnEntry retag, our Span points at the caller. + // See `DiagnosticCx::log_invalidation`. + format!( + "{:?} was later invalidated at offsets {:?} by a {} inside this call", + self.tag, self.range, self.cause + ) + } else { format!( "{:?} was later invalidated at offsets {:?} by a {}", self.tag, self.range, self.cause - ), - self.span.data(), - ) + ) + }; + (message, self.span.data()) } } @@ -82,7 +89,7 @@ impl fmt::Display for InvalidationCause { InvalidationCause::Access(kind) => write!(f, "{}", kind), InvalidationCause::Retag(perm, kind) => if *kind == RetagCause::FnEntry { - write!(f, "{:?} FnEntry retag inside this call", perm) + write!(f, "{:?} FnEntry retag", perm) } else { write!(f, "{:?} retag", perm) }, From 8dc489335325582f05460230c4ee37e4a379c6f2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 22 Sep 2022 09:41:02 +0200 Subject: [PATCH 04/28] GC: factor out visiting all machine values --- src/concurrency/thread.rs | 31 ++++++++-- src/lib.rs | 2 +- src/machine.rs | 14 +++++ src/shims/tls.rs | 13 +++- src/tag_gc.rs | 125 ++++++++++++++++---------------------- 5 files changed, 104 insertions(+), 81 deletions(-) diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index f1a3d19fb4cbc..0788c05be7a1f 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -290,10 +290,6 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { &mut self.threads[self.active_thread].stack } - pub fn iter(&self) -> impl Iterator> { - self.threads.iter() - } - pub fn all_stacks( &self, ) -> impl Iterator>]> { @@ -628,6 +624,33 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { } } +impl VisitMachineValues for ThreadManager<'_, '_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + // FIXME some other fields also contain machine values + let ThreadManager { threads, .. } = self; + + for thread in threads { + // FIXME: implement VisitMachineValues for `Thread` and `Frame` instead. + // In particular we need to visit the `last_error` and `catch_unwind` fields. + if let Some(payload) = thread.panic_payload { + visit(&Operand::Immediate(Immediate::Scalar(payload))) + } + for frame in &thread.stack { + // Return place. + if let Place::Ptr(mplace) = *frame.return_place { + visit(&Operand::Indirect(mplace)); + } + // Locals. + for local in frame.locals.iter() { + if let LocalValue::Live(value) = &local.value { + visit(value); + } + } + } + } + } +} + // Public interface to thread management. impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { diff --git a/src/lib.rs b/src/lib.rs index 6006d6c89dbca..0fe21c9243a9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,7 @@ pub use crate::range_map::RangeMap; pub use crate::stacked_borrows::{ CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks, }; -pub use crate::tag_gc::EvalContextExt as _; +pub use crate::tag_gc::{EvalContextExt as _, VisitMachineValues}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/machine.rs b/src/machine.rs index dcfb998c5645d..9a1621dadc336 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -291,6 +291,9 @@ impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> { } /// The machine itself. +/// +/// If you add anything here that stores machine values, remember to update +/// `visit_all_machine_values`! pub struct MiriMachine<'mir, 'tcx> { // We carry a copy of the global `TyCtxt` for convenience, so methods taking just `&Evaluator` have `tcx` access. pub tcx: TyCtxt<'tcx>, @@ -586,6 +589,17 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { } } +impl VisitMachineValues for MiriMachine<'_, '_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + // FIXME: visit the missing fields: env vars, weak mem, the MemPlace fields in the machine, + // DirHandler, extern_statics, the Stacked Borrows base pointers; maybe more. + let MiriMachine { threads, tls, .. } = self; + + threads.visit_machine_values(visit); + tls.visit_machine_values(visit); + } +} + /// A rustc InterpCx for Miri. pub type MiriInterpCx<'mir, 'tcx> = InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>; diff --git a/src/shims/tls.rs b/src/shims/tls.rs index d93d6a16a0736..d1cee307d774c 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -233,10 +233,17 @@ impl<'tcx> TlsData<'tcx> { data.remove(&thread_id); } } +} + +impl VisitMachineValues for TlsData<'_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + let TlsData { keys, macos_thread_dtors, next_key: _, dtors_running: _ } = self; - pub fn iter(&self, mut visitor: impl FnMut(&Scalar)) { - for scalar in self.keys.values().flat_map(|v| v.data.values()) { - visitor(scalar); + for scalar in keys.values().flat_map(|v| v.data.values()) { + visit(&Operand::Immediate(Immediate::Scalar(*scalar))); + } + for (_, scalar) in macos_thread_dtors.values() { + visit(&Operand::Immediate(Immediate::Scalar(*scalar))); } } } diff --git a/src/tag_gc.rs b/src/tag_gc.rs index e20a86711478a..0bfc81ce01233 100644 --- a/src/tag_gc.rs +++ b/src/tag_gc.rs @@ -1,8 +1,34 @@ -use crate::*; use rustc_data_structures::fx::FxHashSet; +use crate::*; + +pub trait VisitMachineValues { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)); +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { + /// Generic GC helper to visit everything that can store a value. The `acc` offers some chance to + /// accumulate everything. + fn visit_all_machine_values( + &self, + acc: &mut T, + mut visit_operand: impl FnMut(&mut T, &Operand), + mut visit_alloc: impl FnMut(&mut T, &Allocation), + ) { + let this = self.eval_context_ref(); + + // Memory. + this.memory.alloc_map().iter(|it| { + for (_id, (_kind, alloc)) in it { + visit_alloc(acc, alloc); + } + }); + + // And all the other machine values. + this.machine.visit_machine_values(&mut |op| visit_operand(acc, op)); + } + fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // No reason to do anything at all if stacked borrows is off. @@ -12,90 +38,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { let mut tags = FxHashSet::default(); - for thread in this.machine.threads.iter() { - if let Some(Scalar::Ptr( - Pointer { provenance: Provenance::Concrete { sb, .. }, .. }, - _, - )) = thread.panic_payload - { - tags.insert(sb); - } - } - - self.find_tags_in_tls(&mut tags); - self.find_tags_in_memory(&mut tags); - self.find_tags_in_locals(&mut tags)?; - - self.remove_unreachable_tags(tags); - - Ok(()) - } - - fn find_tags_in_tls(&mut self, tags: &mut FxHashSet) { - let this = self.eval_context_mut(); - this.machine.tls.iter(|scalar| { - if let Scalar::Ptr(Pointer { provenance: Provenance::Concrete { sb, .. }, .. }, _) = - scalar - { - tags.insert(*sb); - } - }); - } - - fn find_tags_in_memory(&mut self, tags: &mut FxHashSet) { - let this = self.eval_context_mut(); - this.memory.alloc_map().iter(|it| { - for (_id, (_kind, alloc)) in it { - for (_size, prov) in alloc.provenance().iter() { - if let Provenance::Concrete { sb, .. } = prov { - tags.insert(*sb); - } - } - } - }); - } - - fn find_tags_in_locals(&mut self, tags: &mut FxHashSet) -> InterpResult<'tcx> { - let this = self.eval_context_mut(); - for frame in this.machine.threads.all_stacks().flatten() { - // Handle the return place of each frame - if let Ok(return_place) = frame.return_place.try_as_mplace() { - if let Some(Provenance::Concrete { sb, .. }) = return_place.ptr.provenance { + let visit_scalar = |tags: &mut FxHashSet, s: &Scalar| { + if let Scalar::Ptr(ptr, _) = s { + if let Provenance::Concrete { sb, .. } = ptr.provenance { tags.insert(sb); } } + }; - for local in frame.locals.iter() { - let LocalValue::Live(value) = local.value else { - continue; - }; - match value { - Operand::Immediate(Immediate::Scalar(Scalar::Ptr(ptr, _))) => - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - }, + this.visit_all_machine_values( + &mut tags, + |tags, op| { + match op { + Operand::Immediate(Immediate::Scalar(s)) => { + visit_scalar(tags, s); + } Operand::Immediate(Immediate::ScalarPair(s1, s2)) => { - if let Scalar::Ptr(ptr, _) = s1 { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - } - } - if let Scalar::Ptr(ptr, _) = s2 { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - } - } + visit_scalar(tags, s1); + visit_scalar(tags, s2); } + Operand::Immediate(Immediate::Uninit) => {} Operand::Indirect(MemPlace { ptr, .. }) => { if let Some(Provenance::Concrete { sb, .. }) = ptr.provenance { tags.insert(sb); } } - Operand::Immediate(Immediate::Uninit) - | Operand::Immediate(Immediate::Scalar(Scalar::Int(_))) => {} } - } - } + }, + |tags, alloc| { + for (_size, prov) in alloc.provenance().iter() { + if let Provenance::Concrete { sb, .. } = prov { + tags.insert(*sb); + } + } + }, + ); + + self.remove_unreachable_tags(tags); Ok(()) } From 593457deb335407720eed3176e2df8805deabf7e Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 16 Sep 2022 15:41:25 -0500 Subject: [PATCH 05/28] add flag to specify the number of cpus --- src/bin/miri.rs | 7 +++++++ src/eval.rs | 3 +++ src/lib.rs | 2 +- src/machine.rs | 4 +++- src/shims/unix/foreign_items.rs | 5 ++--- src/shims/windows/foreign_items.rs | 5 ++++- tests/pass/available-parallelism-miri-num-cpus.rs | 8 ++++++++ 7 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 tests/pass/available-parallelism-miri-num-cpus.rs diff --git a/src/bin/miri.rs b/src/bin/miri.rs index 7d32ee4257326..5b16fc2948cbb 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -550,6 +550,13 @@ fn main() { } else { show_error!("-Zmiri-extern-so-file `{}` does not exist", filename); } + } else if let Some(param) = arg.strip_prefix("-Zmiri-num-cpus=") { + let num_cpus = match param.parse::() { + Ok(i) => i, + Err(err) => show_error!("-Zmiri-num-cpus requires a `u32`: {}", err), + }; + + miri_config.num_cpus = num_cpus; } else { // Forward to rustc. rustc_args.push(arg); diff --git a/src/eval.rs b/src/eval.rs index 91a2ac13b1b19..4734d488d0491 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -132,6 +132,8 @@ pub struct MiriConfig { pub external_so_file: Option, /// Run a garbage collector for SbTags every N basic blocks. pub gc_interval: u32, + /// FIXME: add docs. + pub num_cpus: u32, } impl Default for MiriConfig { @@ -164,6 +166,7 @@ impl Default for MiriConfig { retag_fields: false, external_so_file: None, gc_interval: 10_000, + num_cpus: 1, } } } diff --git a/src/lib.rs b/src/lib.rs index 6006d6c89dbca..43455de8c6b2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -104,7 +104,7 @@ pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt}; pub use crate::intptrcast::ProvenanceMode; pub use crate::machine::{ AllocExtra, FrameData, MiriInterpCx, MiriInterpCxExt, MiriMachine, MiriMemoryKind, Provenance, - ProvenanceExtra, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE, + ProvenanceExtra, PAGE_SIZE, STACK_ADDR, STACK_SIZE, }; pub use crate::mono_hash_map::MonoHashMap; pub use crate::operator::EvalContextExt as OperatorEvalContextExt; diff --git a/src/machine.rs b/src/machine.rs index dcfb998c5645d..bd51207bbb19e 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -35,7 +35,6 @@ use crate::{ pub const PAGE_SIZE: u64 = 4 * 1024; // FIXME: adjust to target architecture pub const STACK_ADDR: u64 = 32 * PAGE_SIZE; // not really about the "stack", but where we start assigning integer addresses to allocations pub const STACK_SIZE: u64 = 16 * PAGE_SIZE; // whatever -pub const NUM_CPUS: u64 = 1; /// Extra data stored with each stack frame pub struct FrameData<'tcx> { @@ -407,6 +406,8 @@ pub struct MiriMachine<'mir, 'tcx> { pub(crate) gc_interval: u32, /// The number of blocks that passed since the last SbTag GC pass. pub(crate) since_gc: u32, + /// FIXME: docs, + pub(crate) num_cpus: u32, } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { @@ -486,6 +487,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { }), gc_interval: config.gc_interval, since_gc: 0, + num_cpus: config.num_cpus, } } diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 153e5852dcc88..c21e0441cacf4 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -225,13 +225,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "sysconf" => { let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let name = this.read_scalar(name)?.to_i32()?; - // FIXME: Which of these are POSIX, and which are GNU/Linux? // At least the names seem to all also exist on macOS. let sysconfs: &[(&str, fn(&MiriInterpCx<'_, '_>) -> Scalar)] = &[ ("_SC_PAGESIZE", |this| Scalar::from_int(PAGE_SIZE, this.pointer_size())), - ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())), - ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(NUM_CPUS, this.pointer_size())), + ("_SC_NPROCESSORS_CONF", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), + ("_SC_NPROCESSORS_ONLN", |this| Scalar::from_int(this.machine.num_cpus, this.pointer_size())), // 512 seems to be a reasonable default. The value is not critical, in // the sense that getpwuid_r takes and checks the buffer length. ("_SC_GETPW_R_SIZE_MAX", |this| Scalar::from_int(512, this.pointer_size())) diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index 53ab97b255e56..c5f0de4307c3a 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -163,7 +163,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { )?; // Set number of processors. let num_cpus = system_info.offset(field_offsets[6], dword_layout, &this.tcx)?; - this.write_scalar(Scalar::from_int(NUM_CPUS, dword_layout.size), &num_cpus.into())?; + this.write_scalar( + Scalar::from_int(this.machine.num_cpus, dword_layout.size), + &num_cpus.into(), + )?; } // Thread-local storage diff --git a/tests/pass/available-parallelism-miri-num-cpus.rs b/tests/pass/available-parallelism-miri-num-cpus.rs new file mode 100644 index 0000000000000..137fa51024975 --- /dev/null +++ b/tests/pass/available-parallelism-miri-num-cpus.rs @@ -0,0 +1,8 @@ +//@compile-flags: -Zmiri-num-cpus=1024 + +use std::num::NonZeroUsize; +use std::thread::available_parallelism; + +fn main() { + assert_eq!(available_parallelism().unwrap(), NonZeroUsize::new(1024).unwrap()); +} From 2f8626f8ae2018fbffc6df015b408b594b53a268 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 24 Sep 2022 08:46:34 +0200 Subject: [PATCH 06/28] run all extern-so tests consistently without dependencies --- tests/compiletest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index 6b5668e2d6c4c..4789d22eb4f96 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -213,7 +213,7 @@ fn main() -> Result<()> { ui(Mode::Fail { require_patterns: true }, "tests/fail", WithDependencies)?; if cfg!(target_os = "linux") { ui(Mode::Pass, "tests/extern-so/pass", WithoutDependencies)?; - ui(Mode::Fail { require_patterns: true }, "tests/extern-so/fail", WithDependencies)?; + ui(Mode::Fail { require_patterns: true }, "tests/extern-so/fail", WithoutDependencies)?; } Ok(()) From 04c2411c429781cc37cc3e1fcb82b07487c3aa81 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 24 Sep 2022 20:03:34 +0200 Subject: [PATCH 07/28] remove macOS work-around that is no longer needed --- .github/workflows/ci.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80d150e1df15d..2d26e33545c1d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,14 +38,6 @@ jobs: if: runner.os == 'Linux' run: echo "MIRIFLAGS=-Zmiri-tag-gc=1" >> $GITHUB_ENV - # We install gnu-tar because BSD tar is buggy on macOS builders of GHA. - # See . - - name: Install GNU tar - if: runner.os == 'macOS' - run: | - brew install gnu-tar - echo "/usr/local/opt/gnu-tar/libexec/gnubin" >> $GITHUB_PATH - # Cache the global cargo directory, but NOT the local `target` directory which # we cannot reuse anyway when the nightly changes (and it grows quite large # over time). From 12b86525ba6c02e3b3533e54e57a5d15f8877dff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Sep 2022 09:41:44 +0200 Subject: [PATCH 08/28] CI: use cargo sparse registry --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2d26e33545c1d..c05352f23d67f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,9 @@ on: schedule: - cron: '5 15 * * *' # At 15:05 UTC every day. +env: + CARGO_UNSTABLE_SPARSE_REGISTRY: 'true' + jobs: build: runs-on: ${{ matrix.os }} From e52d92059ea703874307188f1b884a067143853d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Sep 2022 09:44:09 +0200 Subject: [PATCH 09/28] clarify a comment --- src/concurrency/thread.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 0788c05be7a1f..a9d144eff54ab 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -386,6 +386,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { data_race: Option<&mut data_race::GlobalState>, ) -> InterpResult<'tcx> { if self.threads[joined_thread_id].join_status == ThreadJoinStatus::Detached { + // On Windows this corresponds to joining on a closed handle. throw_ub_format!("trying to join a detached thread"); } From d9c6710480218dfc79d32d196cfb6d70ca3a0a75 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Sep 2022 09:46:31 +0200 Subject: [PATCH 10/28] force-install tools on stale cache, to make sure we get the latest of all dependencies --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c05352f23d67f..b62625802f5a8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,8 +64,8 @@ jobs: if: ${{ steps.cache.outputs.cache-hit == 'false' }} shell: bash run: | - cargo install rustup-toolchain-install-master - cargo install xargo + cargo install -f rustup-toolchain-install-master + cargo install -f xargo - name: Install "master" toolchain shell: bash From a773d473a5f8b6d57d26928b243ed14fed72d3f1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 24 Sep 2022 19:57:33 +0200 Subject: [PATCH 11/28] use rustc-build-sysroot instead of xargo --- .github/workflows/ci.yml | 5 +- CONTRIBUTING.md | 2 +- README.md | 2 +- cargo-miri/Cargo.lock | 74 ++++++++++++ cargo-miri/Cargo.toml | 1 + cargo-miri/src/main.rs | 7 +- cargo-miri/src/phases.rs | 16 ++- cargo-miri/src/setup.rs | 247 +++++++++++--------------------------- cargo-miri/src/util.rs | 29 +---- cargo-miri/src/version.rs | 2 - 10 files changed, 166 insertions(+), 219 deletions(-) delete mode 100644 cargo-miri/src/version.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b62625802f5a8..4cda24bb1894e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -57,15 +57,14 @@ jobs: # contains package information of crates installed via `cargo install`. ~/.cargo/.crates.toml ~/.cargo/.crates2.json - key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock', 'cargo-miri/src/version.rs') }} + key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }} restore-keys: ${{ runner.os }}-cargo - - name: Install rustup-toolchain-install-master and xargo + - name: Install rustup-toolchain-install-master if: ${{ steps.cache.outputs.cache-hit == 'false' }} shell: bash run: | cargo install -f rustup-toolchain-install-master - cargo install -f xargo - name: Install "master" toolchain shell: bash diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d965ae8fcb8d..a88e69115ba38 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,7 +38,7 @@ for you. If you don't want all of these to happen, you can add individual `.auto ## Building and testing Miri Invoking Miri requires getting a bunch of flags right and setting up a custom -sysroot with xargo. The `miri` script takes care of that for you. With the +sysroot. The `miri` script takes care of that for you. With the build environment prepared, compiling Miri is just one command away: ``` diff --git a/README.md b/README.md index 2e27bb39afd0f..a1fc5b8440632 100644 --- a/README.md +++ b/README.md @@ -447,7 +447,7 @@ binaries, and as such worth documenting: some compiler flags to prepare the code for interpretation; with `host`, this is not done. This environment variable is useful to be sure that the compiled `rlib`s are compatible with Miri. -* `MIRI_CALLED_FROM_XARGO` is set during the Miri-induced `xargo` sysroot build, +* `MIRI_CALLED_FROM_SETUP` is set during the Miri sysroot build, which will re-invoke `cargo-miri` as the `rustc` to use for this build. * `MIRI_CALLED_FROM_RUSTDOC` when set to any value tells `cargo-miri` that it is running as a child process of `rustdoc`, which invokes it twice for each doc-test diff --git a/cargo-miri/Cargo.lock b/cargo-miri/Cargo.lock index 95c2bda505c5b..1a99957f10fa6 100644 --- a/cargo-miri/Cargo.lock +++ b/cargo-miri/Cargo.lock @@ -35,6 +35,7 @@ version = "0.1.0" dependencies = [ "cargo_metadata", "directories", + "rustc-build-sysroot", "rustc-workspace-hack", "rustc_version", "serde", @@ -142,6 +143,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "getrandom" version = "0.2.3" @@ -322,6 +329,43 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.10" @@ -341,6 +385,26 @@ dependencies = [ "redox_syscall", ] +[[package]] +name = "remove_dir_all" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" +dependencies = [ + "winapi", +] + +[[package]] +name = "rustc-build-sysroot" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea9e30aa5a34196fe1b2899704f1e1dccbc91fa0981f6c36b749899f924fcadd" +dependencies = [ + "anyhow", + "rustc_version", + "tempdir", +] + [[package]] name = "rustc-workspace-hack" version = "1.0.0" @@ -419,6 +483,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempdir" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +dependencies = [ + "rand", + "remove_dir_all", +] + [[package]] name = "thiserror" version = "1.0.30" diff --git a/cargo-miri/Cargo.toml b/cargo-miri/Cargo.toml index 9ac170c5b5377..e9753d3369eeb 100644 --- a/cargo-miri/Cargo.toml +++ b/cargo-miri/Cargo.toml @@ -18,6 +18,7 @@ directories = "3" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.15.0" +rustc-build-sysroot = "0.2.1" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` diff --git a/cargo-miri/src/main.rs b/cargo-miri/src/main.rs index 331c4c9c2b0e7..9b5fa7ae8736e 100644 --- a/cargo-miri/src/main.rs +++ b/cargo-miri/src/main.rs @@ -6,7 +6,6 @@ mod util; mod arg; mod phases; mod setup; -mod version; use std::{env, iter}; @@ -22,8 +21,8 @@ fn main() { // Dispatch to `cargo-miri` phase. Here is a rough idea of "who calls who". // // Initially, we are invoked as `cargo-miri miri run/test`. We first run the setup phase: - // - We call `xargo`, and set `RUSTC` back to us, together with `MIRI_CALLED_FROM_XARGO`, - // so that xargo's rustc invocations end up in `phase_rustc` with `RustcPhase::Setup`. + // - We use `rustc-build-sysroot`, and set `RUSTC` back to us, together with `MIRI_CALLED_FROM_SETUP`, + // so that the sysroot build rustc invocations end up in `phase_rustc` with `RustcPhase::Setup`. // There we then call the Miri driver with `MIRI_BE_RUSTC` to perform the actual build. // // Then we call `cargo run/test`, exactly forwarding all user flags, plus some configuration so @@ -52,7 +51,7 @@ fn main() { // the Miri driver for interpretation. // Dispatch running as part of sysroot compilation. - if env::var_os("MIRI_CALLED_FROM_XARGO").is_some() { + if env::var_os("MIRI_CALLED_FROM_SETUP").is_some() { phase_rustc(args, RustcPhase::Setup); return; } diff --git a/cargo-miri/src/phases.rs b/cargo-miri/src/phases.rs index 93eb3cb174659..a76bb447b9c92 100644 --- a/cargo-miri/src/phases.rs +++ b/cargo-miri/src/phases.rs @@ -7,6 +7,8 @@ use std::io::BufReader; use std::path::PathBuf; use std::process::Command; +use rustc_version::VersionMeta; + use crate::{setup::*, util::*}; const CARGO_MIRI_HELP: &str = r#"Runs binary crates and tests in Miri @@ -90,12 +92,14 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { let verbose = num_arg_flag("-v"); // Determine the involved architectures. - let host = version_info().host; + let rustc_version = VersionMeta::for_command(miri_for_host()) + .expect("failed to determine underlying rustc version of Miri"); + let host = &rustc_version.host; let target = get_arg_flag_value("--target"); - let target = target.as_ref().unwrap_or(&host); + let target = target.as_ref().unwrap_or(host); // We always setup. - setup(&subcommand, &host, target); + setup(&subcommand, target, &rustc_version); // Invoke actual cargo for the job, but with different flags. // We re-use `cargo test` and `cargo run`, which makes target and binary handling very easy but @@ -146,7 +150,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { if get_arg_flag_value("--target").is_none() { // No target given. Explicitly pick the host. cmd.arg("--target"); - cmd.arg(&host); + cmd.arg(host); } // Set ourselves as runner for al binaries invoked by cargo. @@ -204,7 +208,7 @@ pub fn phase_cargo_miri(mut args: impl Iterator) { #[derive(Debug, Copy, Clone, PartialEq)] pub enum RustcPhase { - /// `rustc` called via `xargo` for sysroot build. + /// `rustc` called during sysroot build. Setup, /// `rustc` called by `cargo` for regular build. Build, @@ -264,7 +268,7 @@ pub fn phase_rustc(mut args: impl Iterator, phase: RustcPhase) { let verbose = std::env::var("MIRI_VERBOSE") .map_or(0, |verbose| verbose.parse().expect("verbosity flag must be an integer")); let target_crate = is_target_crate(); - // Determine whether this is cargo/xargo invoking rustc to get some infos. + // Determine whether this is cargo invoking rustc to get some infos. let info_query = get_arg_flag_value("--print").is_some() || has_arg_flag("-vV"); let store_json = |info: CrateRunInfo| { diff --git a/cargo-miri/src/setup.rs b/cargo-miri/src/setup.rs index c27bb18631758..72d8ef2f75224 100644 --- a/cargo-miri/src/setup.rs +++ b/cargo-miri/src/setup.rs @@ -1,64 +1,19 @@ -//! Implements `cargo miri setup` via xargo +//! Implements `cargo miri setup`. use std::env; use std::ffi::OsStr; -use std::fs::{self}; -use std::io::BufRead; -use std::ops::Not; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process::{self, Command}; -use crate::{util::*, version::*}; +use rustc_build_sysroot::{BuildMode, Sysroot, SysrootConfig}; +use rustc_version::VersionMeta; -fn xargo_version() -> Option<(u32, u32, u32)> { - let out = xargo_check().arg("--version").output().ok()?; - if !out.status.success() { - return None; - } - // Parse output. The first line looks like "xargo 0.3.12 (b004f1c 2018-12-13)". - let line = out - .stderr - .lines() - .next() - .expect("malformed `xargo --version` output: not at least one line") - .expect("malformed `xargo --version` output: error reading first line"); - let (name, version) = { - let mut split = line.split(' '); - ( - split.next().expect("malformed `xargo --version` output: empty"), - split.next().expect("malformed `xargo --version` output: not at least two words"), - ) - }; - if name != "xargo" { - // This is some fork of xargo - return None; - } - let mut version_pieces = version.split('.'); - let major = version_pieces - .next() - .expect("malformed `xargo --version` output: not a major version piece") - .parse() - .expect("malformed `xargo --version` output: major version is not an integer"); - let minor = version_pieces - .next() - .expect("malformed `xargo --version` output: not a minor version piece") - .parse() - .expect("malformed `xargo --version` output: minor version is not an integer"); - let patch = version_pieces - .next() - .expect("malformed `xargo --version` output: not a patch version piece") - .parse() - .expect("malformed `xargo --version` output: patch version is not an integer"); - if version_pieces.next().is_some() { - panic!("malformed `xargo --version` output: more than three pieces in version"); - } - Some((major, minor, patch)) -} +use crate::util::*; /// Performs the setup required to make `cargo miri` work: Getting a custom-built libstd. Then sets /// `MIRI_SYSROOT`. Skipped if `MIRI_SYSROOT` is already set, in which case we expect the user has /// done all this already. -pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { +pub fn setup(subcommand: &MiriCommand, target: &str, rustc_version: &VersionMeta) { let only_setup = matches!(subcommand, MiriCommand::Setup); let ask_user = !only_setup; let print_sysroot = only_setup && has_arg_flag("--print-sysroot"); // whether we just print the sysroot path @@ -69,21 +24,8 @@ pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { return; } - // First, we need xargo. - if xargo_version().map_or(true, |v| v < XARGO_MIN_VERSION) { - if std::env::var_os("XARGO_CHECK").is_some() { - // The user manually gave us a xargo binary; don't do anything automatically. - show_error!("xargo is too old; please upgrade to the latest version") - } - let mut cmd = cargo(); - cmd.args(["install", "xargo"]); - ask_to_run(cmd, ask_user, "install a recent enough xargo"); - } - - // Determine where the rust sources are located. The env vars manually setting the source - // (`MIRI_LIB_SRC`, `XARGO_RUST_SRC`) trump auto-detection. - let rust_src_env_var = - std::env::var_os("MIRI_LIB_SRC").or_else(|| std::env::var_os("XARGO_RUST_SRC")); + // Determine where the rust sources are located. The env var trumps auto-detection. + let rust_src_env_var = std::env::var_os("MIRI_LIB_SRC"); let rust_src = match rust_src_env_var { Some(path) => { let path = PathBuf::from(path); @@ -92,22 +34,9 @@ pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { } None => { // Check for `rust-src` rustup component. - let output = miri_for_host() - .args(["--print", "sysroot"]) - .output() - .expect("failed to determine sysroot"); - if !output.status.success() { - show_error!( - "Failed to determine sysroot; Miri said:\n{}", - String::from_utf8_lossy(&output.stderr).trim_end() - ); - } - let sysroot = std::str::from_utf8(&output.stdout).unwrap(); - let sysroot = Path::new(sysroot.trim_end_matches('\n')); - // Check for `$SYSROOT/lib/rustlib/src/rust/library`; test if that contains `std/Cargo.toml`. - let rustup_src = - sysroot.join("lib").join("rustlib").join("src").join("rust").join("library"); - if !rustup_src.join("std").join("Cargo.toml").exists() { + let rustup_src = rustc_build_sysroot::rustc_sysroot_src(miri_for_host()) + .expect("could not determine sysroot source directory"); + if !rustup_src.exists() { // Ask the user to install the `rust-src` component, and use that. let mut cmd = Command::new("rustup"); cmd.args(["component", "add", "rust-src"]); @@ -131,115 +60,85 @@ pub fn setup(subcommand: &MiriCommand, host: &str, target: &str) { ); } - // Next, we need our own libstd. Prepare a xargo project for that purpose. - // We will do this work in whatever is a good cache dir for this platform. - let dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap(); - let dir = dirs.cache_dir(); - if !dir.exists() { - fs::create_dir_all(dir).unwrap(); - } - // The interesting bit: Xargo.toml (only needs content if we actually need std) - let xargo_toml = if std::env::var_os("MIRI_NO_STD").is_some() { - "" + // Determine where to put the sysroot. + let user_dirs = directories::ProjectDirs::from("org", "rust-lang", "miri").unwrap(); + let sysroot_dir = user_dirs.cache_dir(); + // Sysroot configuration and build details. + let sysroot_config = if std::env::var_os("MIRI_NO_STD").is_some() { + SysrootConfig::NoStd } else { - r#" -[dependencies.std] -default_features = false -# We support unwinding, so enable that panic runtime. -features = ["panic_unwind", "backtrace"] - -[dependencies.test] -"# + SysrootConfig::WithStd { std_features: &["panic_unwind", "backtrace"] } }; - write_to_file(&dir.join("Xargo.toml"), xargo_toml); - // The boring bits: a dummy project for xargo. - // FIXME: With xargo-check, can we avoid doing this? - write_to_file( - &dir.join("Cargo.toml"), - r#" -[package] -name = "miri-xargo" -description = "A dummy project for building libstd with xargo." -version = "0.0.0" - -[lib] -path = "lib.rs" -"#, - ); - write_to_file(&dir.join("lib.rs"), "#![no_std]"); + let cargo_cmd = || { + let mut command = cargo(); + // Use Miri as rustc to build a libstd compatible with us (and use the right flags). + // However, when we are running in bootstrap, we cannot just overwrite `RUSTC`, + // because we still need bootstrap to distinguish between host and target crates. + // In that case we overwrite `RUSTC_REAL` instead which determines the rustc used + // for target crates. + // We set ourselves (`cargo-miri`) instead of Miri directly to be able to patch the flags + // for `libpanic_abort` (usually this is done by bootstrap but we have to do it ourselves). + // The `MIRI_CALLED_FROM_SETUP` will mean we dispatch to `phase_setup_rustc`. + let cargo_miri_path = std::env::current_exe().expect("current executable path invalid"); + if env::var_os("RUSTC_STAGE").is_some() { + assert!(env::var_os("RUSTC").is_some()); + command.env("RUSTC_REAL", &cargo_miri_path); + } else { + command.env("RUSTC", &cargo_miri_path); + } + command.env("MIRI_CALLED_FROM_SETUP", "1"); + // Make sure there are no other wrappers getting in our way (Cc + // https://github.com/rust-lang/miri/issues/1421, + // https://github.com/rust-lang/miri/issues/2429). Looks like setting + // `RUSTC_WRAPPER` to the empty string overwrites `build.rustc-wrapper` set via + // `config.toml`. + command.env("RUSTC_WRAPPER", ""); - // Figure out where xargo will build its stuff. - // Unfortunately, it puts things into a different directory when the - // architecture matches the host. - let sysroot = if target == host { dir.join("HOST") } else { PathBuf::from(dir) }; + if only_setup { + if print_sysroot { + // Be extra sure there is no noise on stdout. + command.stdout(process::Stdio::null()); + } + } else { + command.stdout(process::Stdio::null()); + command.stderr(process::Stdio::null()); + } + // Disable debug assertions in the standard library -- Miri is already slow enough. + // But keep the overflow checks, they are cheap. This completely overwrites flags + // the user might have set, which is consistent with normal `cargo build` that does + // not apply `RUSTFLAGS` to the sysroot either. + let rustflags = vec!["-Cdebug-assertions=off".into(), "-Coverflow-checks=on".into()]; + (command, rustflags) + }; // Make sure all target-level Miri invocations know their sysroot. - std::env::set_var("MIRI_SYSROOT", &sysroot); + std::env::set_var("MIRI_SYSROOT", sysroot_dir); - // Now invoke xargo. - let mut command = xargo_check(); - command.arg("check").arg("-q"); - command.current_dir(dir); - command.env("XARGO_HOME", dir); - command.env("XARGO_RUST_SRC", &rust_src); - // We always need to set a target so rustc bootstrap can tell apart host from target crates. - command.arg("--target").arg(target); - // Use Miri as rustc to build a libstd compatible with us (and use the right flags). - // However, when we are running in bootstrap, we cannot just overwrite `RUSTC`, - // because we still need bootstrap to distinguish between host and target crates. - // In that case we overwrite `RUSTC_REAL` instead which determines the rustc used - // for target crates. - // We set ourselves (`cargo-miri`) instead of Miri directly to be able to patch the flags - // for `libpanic_abort` (usually this is done by bootstrap but we have to do it ourselves). - // The `MIRI_CALLED_FROM_XARGO` will mean we dispatch to `phase_setup_rustc`. - let cargo_miri_path = std::env::current_exe().expect("current executable path invalid"); - if env::var_os("RUSTC_STAGE").is_some() { - assert!(env::var_os("RUSTC").is_some()); - command.env("RUSTC_REAL", &cargo_miri_path); - } else { - command.env("RUSTC", &cargo_miri_path); - } - command.env("MIRI_CALLED_FROM_XARGO", "1"); - // Make sure there are no other wrappers getting in our way - // (Cc https://github.com/rust-lang/miri/issues/1421, https://github.com/rust-lang/miri/issues/2429). - // Looks like setting `RUSTC_WRAPPER` to the empty string overwrites `build.rustc-wrapper` set via `config.toml`. - command.env("RUSTC_WRAPPER", ""); - // Disable debug assertions in the standard library -- Miri is already slow enough. But keep the - // overflow checks, they are cheap. This completely overwrites flags the user might have set, - // which is consistent with normal `cargo build` that does not apply `RUSTFLAGS` to the sysroot - // either. - command.env("RUSTFLAGS", "-Cdebug-assertions=off -Coverflow-checks=on"); - // Manage the output the user sees. + // Do the build. if only_setup { // We want to be explicit. eprintln!("Preparing a sysroot for Miri (target: {target})..."); - if print_sysroot { - // Be extra sure there is no noise on stdout. - command.stdout(process::Stdio::null()); - } } else { // We want to be quiet, but still let the user know that something is happening. eprint!("Preparing a sysroot for Miri (target: {target})... "); - command.stdout(process::Stdio::null()); - command.stderr(process::Stdio::null()); } - - // Finally run it! - if command.status().expect("failed to run xargo").success().not() { - if only_setup { - show_error!("failed to run xargo, see error details above") - } else { - show_error!("failed to run xargo; run `cargo miri setup` to see the error details") - } - } - - // Figure out what to print. + Sysroot::new(sysroot_dir, target) + .build_from_source(&rust_src, BuildMode::Check, sysroot_config, rustc_version, cargo_cmd) + .unwrap_or_else(|_| { + if only_setup { + show_error!("failed to build sysroot, see error details above") + } else { + show_error!( + "failed to build sysroot; run `cargo miri setup` to see the error details" + ) + } + }); if only_setup { - eprintln!("A sysroot for Miri is now available in `{}`.", sysroot.display()); + eprintln!("A sysroot for Miri is now available in `{}`.", sysroot_dir.display()); } else { eprintln!("done"); } if print_sysroot { // Print just the sysroot and nothing else to stdout; this way we do not need any escaping. - println!("{}", sysroot.display()); + println!("{}", sysroot_dir.display()); } } diff --git a/cargo-miri/src/util.rs b/cargo-miri/src/util.rs index 8f29eebaac100..aabe5547e5c9a 100644 --- a/cargo-miri/src/util.rs +++ b/cargo-miri/src/util.rs @@ -2,14 +2,13 @@ use std::collections::HashMap; use std::env; use std::ffi::OsString; use std::fmt::Write as _; -use std::fs::{self, File}; +use std::fs::File; use std::io::{self, BufWriter, Read, Write}; use std::ops::Not; use std::path::{Path, PathBuf}; use std::process::Command; use cargo_metadata::{Metadata, MetadataCommand}; -use rustc_version::VersionMeta; use serde::{Deserialize, Serialize}; pub use crate::arg::*; @@ -111,19 +110,10 @@ pub fn miri_for_host() -> Command { cmd } -pub fn version_info() -> VersionMeta { - VersionMeta::for_command(miri_for_host()) - .expect("failed to determine underlying rustc version of Miri") -} - pub fn cargo() -> Command { Command::new(env::var_os("CARGO").unwrap_or_else(|| OsString::from("cargo"))) } -pub fn xargo_check() -> Command { - Command::new(env::var_os("XARGO_CHECK").unwrap_or_else(|| OsString::from("xargo-check"))) -} - /// Execute the `Command`, where possible by replacing the current process with a new process /// described by the `Command`. Then exit this process with the exit code of the new process. pub fn exec(mut cmd: Command) -> ! { @@ -203,23 +193,6 @@ pub fn ask_to_run(mut cmd: Command, ask: bool, text: &str) { } } -/// Writes the given content to the given file *cross-process atomically*, in the sense that another -/// process concurrently reading that file will see either the old content or the new content, but -/// not some intermediate (e.g., empty) state. -/// -/// We assume no other parts of this same process are trying to read or write that file. -pub fn write_to_file(filename: &Path, content: &str) { - // Create a temporary file with the desired contents. - let mut temp_filename = filename.as_os_str().to_os_string(); - temp_filename.push(&format!(".{}", std::process::id())); - let mut temp_file = File::create(&temp_filename).unwrap(); - temp_file.write_all(content.as_bytes()).unwrap(); - drop(temp_file); - - // Move file to the desired location. - fs::rename(temp_filename, filename).unwrap(); -} - // Computes the extra flags that need to be passed to cargo to make it behave like the current // cargo invocation. fn cargo_extra_flags() -> Vec { diff --git a/cargo-miri/src/version.rs b/cargo-miri/src/version.rs deleted file mode 100644 index 366e90df17983..0000000000000 --- a/cargo-miri/src/version.rs +++ /dev/null @@ -1,2 +0,0 @@ -// We put this in a separate file so that it can be hashed for GHA caching. -pub const XARGO_MIN_VERSION: (u32, u32, u32) = (0, 3, 26); From 4a249d952226494cd7e8e02a42ce537a6d05f8be Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Mon, 26 Sep 2022 11:40:23 -0500 Subject: [PATCH 12/28] `/// FIXME: docs` --- src/eval.rs | 2 +- src/machine.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 4734d488d0491..b211f3c5f7133 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -132,7 +132,7 @@ pub struct MiriConfig { pub external_so_file: Option, /// Run a garbage collector for SbTags every N basic blocks. pub gc_interval: u32, - /// FIXME: add docs. + /// The number of CPUs to be reported by miri. pub num_cpus: u32, } diff --git a/src/machine.rs b/src/machine.rs index bd51207bbb19e..805657ac18220 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -406,7 +406,7 @@ pub struct MiriMachine<'mir, 'tcx> { pub(crate) gc_interval: u32, /// The number of blocks that passed since the last SbTag GC pass. pub(crate) since_gc: u32, - /// FIXME: docs, + /// The number of CPUs to be reported by miri. pub(crate) num_cpus: u32, } From f9efbac557293eeeb0b248e1757979960b85fd26 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Mon, 26 Sep 2022 15:24:38 -0500 Subject: [PATCH 13/28] update readme --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e27bb39afd0f..bb9b002c6899f 100644 --- a/README.md +++ b/README.md @@ -293,6 +293,9 @@ environment variable. We first document the most relevant and most commonly used value of forwarded variables stays the same. Has no effect if `-Zmiri-disable-isolation` is set. * `-Zmiri-ignore-leaks` disables the memory leak checker, and also allows some remaining threads to exist when the main thread exits. +* `-Zmiri-num-cpus` states the number of available CPUs to be reported by miri. By default, the + number of available CPUs is `1`. Note that this flag does not affect how miri handles threads in + any way. * `-Zmiri-permissive-provenance` disables the warning for integer-to-pointer casts and [`ptr::from_exposed_addr`](https://doc.rust-lang.org/nightly/std/ptr/fn.from_exposed_addr.html). This will necessarily miss some bugs as those operations are not efficiently and accurately @@ -357,7 +360,7 @@ to Miri failing to detect cases of undefined behavior in a program. This is **work in progress**; currently, only integer arguments and return values are supported (and no, pointer/integer casts to work around this limitation will not work; they will fail horribly). It also only works on unix hosts for now. - Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365). + Follow [the discussion on supporting other types](https://github.com/rust-lang/miri/issues/2365). * `-Zmiri-measureme=` enables `measureme` profiling for the interpreted program. This can be used to find which parts of your program are executing slowly under Miri. The profile is written out to a file with the prefix ``, and can be processed @@ -387,7 +390,7 @@ to Miri failing to detect cases of undefined behavior in a program. Borrows "protectors". Specifying this argument multiple times does not overwrite the previous values, instead it appends its values to the list. Listing an id multiple times has no effect. * `-Zmiri-track-pointer-tag=,,...` shows a backtrace when a given pointer tag - is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid + is created and when (if ever) it is popped from a borrow stack (which is where the tag becomes invalid and any future use of it will error). This helps you in finding out why UB is happening and where in your code would be a good place to look for it. Specifying this argument multiple times does not overwrite the previous From 2e97d2b5ecfdd99cd06445f94777abc0f07dd6b1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Sep 2022 22:34:07 +0200 Subject: [PATCH 14/28] cargo update --- Cargo.lock | 187 +++++++++++----------- cargo-miri/Cargo.lock | 293 ++++++++++++++--------------------- cargo-miri/Cargo.toml | 6 +- test-cargo-miri/Cargo.lock | 20 +-- test_dependencies/Cargo.lock | 52 +++---- 5 files changed, 243 insertions(+), 315 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9df35ec0deb2e..5a4bb65449470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" dependencies = [ "memchr", ] @@ -45,9 +45,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" dependencies = [ "addr2line", "cc", @@ -66,9 +66,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "camino" -version = "1.0.9" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ "serde", ] @@ -109,9 +109,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "color-eyre" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ebf286c900a6d5867aeff75cfee3192857bb7f24b547d4f0df2ed6baa812c90" +checksum = "5a667583cca8c4f8436db8de46ea8233c42a7d9ae424a82d338f2e4675229204" dependencies = [ "backtrace", "color-spantrace", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "crossbeam" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845" +checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" dependencies = [ "cfg-if", "crossbeam-channel", @@ -161,9 +161,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" dependencies = [ "cfg-if", "crossbeam-utils", @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -182,23 +182,23 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-queue" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f25d8400f4a7a5778f0e4e52384a48cbd9b5c495d110786187fc750075277a2" +checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" dependencies = [ "cfg-if", "crossbeam-utils", @@ -206,12 +206,12 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" dependencies = [ "cfg-if", - "lazy_static", + "once_cell", ] [[package]] @@ -222,9 +222,9 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" dependencies = [ "atty", "humantime", @@ -245,9 +245,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -256,9 +256,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" [[package]] name = "hermit-abi" @@ -292,9 +292,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "lazy_static" @@ -304,9 +304,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.112" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "libffi" @@ -339,18 +339,19 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.5" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ + "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] @@ -371,9 +372,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" @@ -395,9 +396,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" dependencies = [ "adler", ] @@ -425,24 +426,24 @@ dependencies = [ [[package]] name = "object" -version = "0.28.4" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.13.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "owo-colors" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf7381921fea4dcb2549c5667eda59b3ec297ab7e2b5fc33eac69d2e7da87b" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "parking_lot" @@ -486,38 +487,37 @@ checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "rand" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] @@ -532,36 +532,27 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core", -] - [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.5.5" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a11647b6b25ff05a515cb92c365cec08801e83423a235b51e231e1808747286" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -570,9 +561,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "rustc-demangle" @@ -603,9 +594,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "scopeguard" @@ -615,27 +606,27 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.9" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -644,9 +635,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -670,15 +661,15 @@ checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f" [[package]] name = "smallvec" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ecab6c735a6bb4139c0caafd0cc3635748bbb3acf4550e8138122099251f309" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "syn" -version = "1.0.95" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -687,9 +678,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -705,9 +696,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" dependencies = [ "cfg-if", "pin-project-lite", @@ -716,9 +707,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" dependencies = [ "once_cell", "valuable", @@ -736,9 +727,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a713421342a5a666b7577783721d3117f1b69a393df803ee17bb73b1e122a59" +checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" dependencies = [ "sharded-slab", "thread_local", @@ -765,9 +756,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "valuable" @@ -777,9 +768,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" diff --git a/cargo-miri/Cargo.lock b/cargo-miri/Cargo.lock index 1a99957f10fa6..763ec45bbfd6f 100644 --- a/cargo-miri/Cargo.lock +++ b/cargo-miri/Cargo.lock @@ -4,15 +4,9 @@ version = 3 [[package]] name = "anyhow" -version = "1.0.51" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b26702f315f53b6071259e15dd9d64528213b44d61de1ec926eca7715d62203" - -[[package]] -name = "autocfg" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "98161a4e3e2184da77bb14f02184cdd111e83bbbcc9979dfee3c44b9a85f5602" [[package]] name = "bitflags" @@ -22,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "camino" -version = "1.0.9" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "869119e97797867fd90f5e22af7d0bd274bd4635ebb9eb68c04f3f513ae6c412" +checksum = "88ad0e1e3e88dd237a156ab9f571021b8a158caa0ae44b1968a241efb5144c1e" dependencies = [ "serde", ] @@ -67,9 +61,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" dependencies = [ "jobserver", ] @@ -80,33 +74,20 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "time", - "winapi", -] - [[package]] name = "directories" -version = "3.0.2" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e69600ff1703123957937708eb27f7a564e48885c537782722ed0ba3189ce1d7" +checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -115,18 +96,18 @@ dependencies = [ [[package]] name = "enum-iterator" -version = "0.7.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401" dependencies = [ "enum-iterator-derive", ] [[package]] name = "enum-iterator-derive" -version = "0.7.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ "proc-macro2", "quote", @@ -134,26 +115,28 @@ dependencies = [ ] [[package]] -name = "form_urlencoded" -version = "1.0.1" +name = "fastrand" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ - "matches", - "percent-encoding", + "instant", ] [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "form_urlencoded" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +dependencies = [ + "percent-encoding", +] [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", @@ -174,9 +157,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.13.25" +version = "0.14.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29229cc1b24c0e6062f6e742aa3e256492a5323365e5ed3413599f8a5eff7d6" +checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" dependencies = [ "bitflags", "libc", @@ -187,41 +170,49 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "jobserver" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" dependencies = [ "libc", ] [[package]] name = "libc" -version = "0.2.112" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "libgit2-sys" -version = "0.12.26+1.3.0" +version = "0.13.4+1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e1c899248e606fbfe68dcb31d8b0176ebab833b103824af31bddf4b7457494" +checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" dependencies = [ "cc", "libc", @@ -231,9 +222,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.3" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de5435b8549c16d423ed0c03dbaafe57cf6c3344744f1242520d59c9d8ecec66" +checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" dependencies = [ "cc", "libc", @@ -243,49 +234,33 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] -name = "matches" -version = "0.1.9" +name = "num_threads" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", + "libc", ] [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pkg-config" -version = "0.3.24" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "proc-macro-error" @@ -313,76 +288,40 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.42" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.10" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", "redox_syscall", + "thiserror", ] [[package]] @@ -396,13 +335,13 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.2.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e30aa5a34196fe1b2899704f1e1dccbc91fa0981f6c36b749899f924fcadd" +checksum = "3d7cb0915a85234cee53b853ca8c2538ddfd7f3bf6d2501b52d1d37aba6c7bef" dependencies = [ "anyhow", "rustc_version", - "tempdir", + "tempfile", ] [[package]] @@ -422,39 +361,39 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "semver" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2333e6df6d6598f2b1974829f853c2b4c5f4a6e503c10af918081aa6f8564e1" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" dependencies = [ "serde", ] [[package]] name = "serde" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.140" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -463,9 +402,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", @@ -474,9 +413,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -484,29 +423,33 @@ dependencies = [ ] [[package]] -name = "tempdir" -version = "0.3.7" +name = "tempfile" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ - "rand", + "cfg-if", + "fastrand", + "libc", + "redox_syscall", "remove_dir_all", + "winapi", ] [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", @@ -515,19 +458,20 @@ dependencies = [ [[package]] name = "time" -version = "0.1.43" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" dependencies = [ + "itoa", "libc", - "winapi", + "num_threads", ] [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -540,34 +484,33 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] @@ -579,31 +522,31 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "5.1.17" +version = "7.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cf88d94e969e7956d924ba70741316796177fa0c79a2c9f4ab04998d96e966e" +checksum = "73ba753d713ec3844652ad2cb7eb56bc71e34213a14faddac7852a10ba88f61e" dependencies = [ "anyhow", "cfg-if", - "chrono", "enum-iterator", "getset", "git2", "rustversion", "thiserror", + "time", ] [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "winapi" diff --git a/cargo-miri/Cargo.toml b/cargo-miri/Cargo.toml index e9753d3369eeb..9cd88ea48cdcf 100644 --- a/cargo-miri/Cargo.toml +++ b/cargo-miri/Cargo.toml @@ -14,11 +14,11 @@ test = false # we have no unit tests doctest = false # and no doc tests [dependencies] -directories = "3" +directories = "4" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.15.0" -rustc-build-sysroot = "0.2.1" +rustc-build-sysroot = "0.3" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` @@ -30,4 +30,4 @@ rustc-workspace-hack = "1.0.0" serde = { version = "*", features = ["derive"] } [build-dependencies] -vergen = { version = "5", default_features = false, features = ["git"] } +vergen = { version = "7.4", default_features = false, features = ["git"] } diff --git a/test-cargo-miri/Cargo.lock b/test-cargo-miri/Cargo.lock index a297dd27dbc94..2c53c482bf9aa 100644 --- a/test-cargo-miri/Cargo.lock +++ b/test-cargo-miri/Cargo.lock @@ -83,27 +83,27 @@ version = "0.1.0" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote", @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -130,6 +130,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" diff --git a/test_dependencies/Cargo.lock b/test_dependencies/Cargo.lock index d4b32e2c29a22..78cf9a8d51bcb 100644 --- a/test_dependencies/Cargo.lock +++ b/test_dependencies/Cargo.lock @@ -16,9 +16,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" [[package]] name = "cfg-if" @@ -59,15 +59,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.126" +version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" dependencies = [ "autocfg", "scopeguard", @@ -123,12 +123,6 @@ dependencies = [ "libc", ] -[[package]] -name = "once_cell" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" - [[package]] name = "page_size" version = "0.4.2" @@ -176,18 +170,18 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "3edcd08cf4fea98d1ae6c9ddd3b8ccb1acac7c3693d62625969a7daa04a2ae36" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -215,18 +209,18 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom 0.2.7", ] [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags", ] @@ -254,9 +248,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" dependencies = [ "libc", "winapi", @@ -264,9 +258,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2" dependencies = [ "proc-macro2", "quote", @@ -275,16 +269,16 @@ dependencies = [ [[package]] name = "tokio" -version = "1.19.2" +version = "1.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" dependencies = [ + "autocfg", "bytes", "libc", "memchr", "mio", "num_cpus", - "once_cell", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -306,9 +300,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" [[package]] name = "wasi" From eec79492f2eccbd6392156620e83a335403df9d5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 28 Sep 2022 22:38:38 +0200 Subject: [PATCH 15/28] no need to make cargo-miri build quiet; cargo only prints to stderr anyway --- miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miri b/miri index 19f1a987ace4a..e492308a62eb5 100755 --- a/miri +++ b/miri @@ -138,7 +138,7 @@ export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR $RUSTFLAGS" # Build a sysroot and set MIRI_SYSROOT to use it. Arguments are passed to `cargo miri setup`. build_sysroot() { - if ! MIRI_SYSROOT="$($CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -q -- miri setup --print-sysroot "$@")"; then + if ! MIRI_SYSROOT="$($CARGO run $CARGO_EXTRA_FLAGS --manifest-path "$MIRIDIR"/cargo-miri/Cargo.toml -- miri setup --print-sysroot "$@")"; then echo "'cargo miri setup' failed" exit 1 fi From a214877b07eb077c5b3c4f8c389616eb2ff71e61 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Sep 2022 10:19:49 +0200 Subject: [PATCH 16/28] bump rustc-build-sysroot --- cargo-miri/Cargo.lock | 4 ++-- cargo-miri/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cargo-miri/Cargo.lock b/cargo-miri/Cargo.lock index 763ec45bbfd6f..f137cafe96afe 100644 --- a/cargo-miri/Cargo.lock +++ b/cargo-miri/Cargo.lock @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7cb0915a85234cee53b853ca8c2538ddfd7f3bf6d2501b52d1d37aba6c7bef" +checksum = "ec5f3689b6c560d6a3a17fcbe54204cd870b4fcf46342d60de16715b660d2c92" dependencies = [ "anyhow", "rustc_version", diff --git a/cargo-miri/Cargo.toml b/cargo-miri/Cargo.toml index 9cd88ea48cdcf..b06b590e67059 100644 --- a/cargo-miri/Cargo.toml +++ b/cargo-miri/Cargo.toml @@ -18,7 +18,7 @@ directories = "4" rustc_version = "0.4" serde_json = "1.0.40" cargo_metadata = "0.15.0" -rustc-build-sysroot = "0.3" +rustc-build-sysroot = "0.3.3" # A noop dependency that changes in the Rust repository, it's a bit of a hack. # See the `src/tools/rustc-workspace-hack/README.md` file in `rust-lang/rust` From 67b9cd4515e9bf6b02fea8e00caacf52e64957b4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Sep 2022 10:33:37 +0200 Subject: [PATCH 17/28] GHA seems to have strange booleans --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4cda24bb1894e..923f83913662f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -61,7 +61,7 @@ jobs: restore-keys: ${{ runner.os }}-cargo - name: Install rustup-toolchain-install-master - if: ${{ steps.cache.outputs.cache-hit == 'false' }} + if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }} shell: bash run: | cargo install -f rustup-toolchain-install-master From dc4738ef778c0423ac0375e8fb5172a3cc743cab Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Sep 2022 11:28:31 +0200 Subject: [PATCH 18/28] relax vergen dependency --- cargo-miri/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cargo-miri/Cargo.toml b/cargo-miri/Cargo.toml index b06b590e67059..3c1f259d88df5 100644 --- a/cargo-miri/Cargo.toml +++ b/cargo-miri/Cargo.toml @@ -30,4 +30,4 @@ rustc-workspace-hack = "1.0.0" serde = { version = "*", features = ["derive"] } [build-dependencies] -vergen = { version = "7.4", default_features = false, features = ["git"] } +vergen = { version = "7", default_features = false, features = ["git"] } From d26695290fd36fa84c17ca3e2fe38d1295190f12 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 29 Sep 2022 13:23:44 +0200 Subject: [PATCH 19/28] use rustc_tools_util instead of vergen --- cargo-miri/Cargo.lock | 254 ++------------------------------------- cargo-miri/Cargo.toml | 2 +- cargo-miri/build.rs | 16 +-- cargo-miri/src/phases.rs | 17 +-- 4 files changed, 23 insertions(+), 266 deletions(-) diff --git a/cargo-miri/Cargo.lock b/cargo-miri/Cargo.lock index f137cafe96afe..0608553dd1964 100644 --- a/cargo-miri/Cargo.lock +++ b/cargo-miri/Cargo.lock @@ -31,10 +31,10 @@ dependencies = [ "directories", "rustc-build-sysroot", "rustc-workspace-hack", + "rustc_tools_util", "rustc_version", "serde", "serde_json", - "vergen", ] [[package]] @@ -59,15 +59,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "cc" -version = "1.0.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" -dependencies = [ - "jobserver", -] - [[package]] name = "cfg-if" version = "1.0.0" @@ -94,26 +85,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "enum-iterator" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "fastrand" version = "1.8.0" @@ -123,15 +94,6 @@ dependencies = [ "instant", ] -[[package]] -name = "form_urlencoded" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" -dependencies = [ - "percent-encoding", -] - [[package]] name = "getrandom" version = "0.2.7" @@ -143,41 +105,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "getset" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "git2" -version = "0.14.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" -dependencies = [ - "bitflags", - "libc", - "libgit2-sys", - "log", - "url", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - [[package]] name = "instant" version = "0.1.12" @@ -193,99 +120,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" -[[package]] -name = "jobserver" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" -dependencies = [ - "libc", -] - [[package]] name = "libc" version = "0.2.133" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" -[[package]] -name = "libgit2-sys" -version = "0.13.4+1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" -dependencies = [ - "cc", - "libc", - "libz-sys", - "pkg-config", -] - -[[package]] -name = "libz-sys" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9702761c3935f8cc2f101793272e202c72b99da8f4224a19ddcf1279a6450bbf" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" -dependencies = [ - "libc", -] - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "pkg-config" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - [[package]] name = "proc-macro2" version = "1.0.45" @@ -350,6 +190,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" +[[package]] +name = "rustc_tools_util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" + [[package]] name = "rustc_version" version = "0.4.0" @@ -359,12 +205,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustversion" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" - [[package]] name = "ryu" version = "1.0.11" @@ -456,92 +296,12 @@ dependencies = [ "syn", ] -[[package]] -name = "time" -version = "0.3.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3f9a28b618c3a6b9251b6908e9c99e04b9e5c02e6581ccbb67d59c34ef7f9b" -dependencies = [ - "itoa", - "libc", - "num_threads", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" - -[[package]] -name = "unicode-bidi" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" - [[package]] name = "unicode-ident" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd" -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "vergen" -version = "7.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ba753d713ec3844652ad2cb7eb56bc71e34213a14faddac7852a10ba88f61e" -dependencies = [ - "anyhow", - "cfg-if", - "enum-iterator", - "getset", - "git2", - "rustversion", - "thiserror", - "time", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/cargo-miri/Cargo.toml b/cargo-miri/Cargo.toml index 3c1f259d88df5..fcdd122747da5 100644 --- a/cargo-miri/Cargo.toml +++ b/cargo-miri/Cargo.toml @@ -30,4 +30,4 @@ rustc-workspace-hack = "1.0.0" serde = { version = "*", features = ["derive"] } [build-dependencies] -vergen = { version = "7", default_features = false, features = ["git"] } +rustc_tools_util = "0.2" diff --git a/cargo-miri/build.rs b/cargo-miri/build.rs index ebd8e7003d5f7..c111011545590 100644 --- a/cargo-miri/build.rs +++ b/cargo-miri/build.rs @@ -1,11 +1,13 @@ -use vergen::vergen; - fn main() { // Don't rebuild miri when nothing changed. println!("cargo:rerun-if-changed=build.rs"); - // vergen - let mut gen_config = vergen::Config::default(); - *gen_config.git_mut().sha_kind_mut() = vergen::ShaKind::Short; - *gen_config.git_mut().commit_timestamp_kind_mut() = vergen::TimestampKind::DateOnly; - vergen(gen_config).ok(); // Ignore failure (in case we are built outside a git repo) + // gather version info + println!( + "cargo:rustc-env=GIT_HASH={}", + rustc_tools_util::get_commit_hash().unwrap_or_default() + ); + println!( + "cargo:rustc-env=COMMIT_DATE={}", + rustc_tools_util::get_commit_date().unwrap_or_default() + ); } diff --git a/cargo-miri/src/phases.rs b/cargo-miri/src/phases.rs index a76bb447b9c92..0c1f039d6cc09 100644 --- a/cargo-miri/src/phases.rs +++ b/cargo-miri/src/phases.rs @@ -1,7 +1,6 @@ //! Implements the various phases of `cargo miri run/test`. use std::env; -use std::fmt::Write as _; use std::fs::{self, File}; use std::io::BufReader; use std::path::PathBuf; @@ -39,17 +38,13 @@ fn show_help() { } fn show_version() { - let mut version = format!("miri {}", env!("CARGO_PKG_VERSION")); - // Only use `option_env` on vergen variables to ensure the build succeeds - // when vergen failed to find the git info. - if let Some(sha) = option_env!("VERGEN_GIT_SHA_SHORT") { - // This `unwrap` can never fail because if VERGEN_GIT_SHA_SHORT exists, then so does - // VERGEN_GIT_COMMIT_DATE. - #[allow(clippy::option_env_unwrap)] - write!(&mut version, " ({} {})", sha, option_env!("VERGEN_GIT_COMMIT_DATE").unwrap()) - .unwrap(); + print!("miri {}", env!("CARGO_PKG_VERSION")); + let version = format!("{} {}", env!("GIT_HASH"), env!("COMMIT_DATE")); + if version.len() > 1 { + // If there is actually something here, print it. + print!(" ({version})"); } - println!("{}", version); + println!(); } fn forward_patched_extern_arg(args: &mut impl Iterator, cmd: &mut Command) { From d867ce144fce19ada0b8dc74e6868cf0e3b62b33 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 2 Oct 2022 12:10:15 +0200 Subject: [PATCH 20/28] bump rustc_tools_util --- cargo-miri/Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cargo-miri/Cargo.lock b/cargo-miri/Cargo.lock index 0608553dd1964..2beb6e1f1a463 100644 --- a/cargo-miri/Cargo.lock +++ b/cargo-miri/Cargo.lock @@ -192,9 +192,9 @@ checksum = "fc71d2faa173b74b232dedc235e3ee1696581bb132fc116fa3626d6151a1a8fb" [[package]] name = "rustc_tools_util" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" +checksum = "598f48ce2a421542b3e64828aa742b687cc1b91d2f96591cfdb7ac5988cd6366" [[package]] name = "rustc_version" From cbb89578357d4628a7bdb3fde8d6417bcaadcdd1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 4 Oct 2022 13:15:32 +0200 Subject: [PATCH 21/28] more details on stacked borrows tracking --- src/diagnostics.rs | 22 ++++++++++++++-------- src/stacked_borrows/mod.rs | 21 +++++++++++++++++++-- 2 files changed, 33 insertions(+), 10 deletions(-) diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 868c85c04a88d..ecfe0cd3f8a65 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -60,7 +60,10 @@ impl MachineStopType for TerminationInfo {} /// Miri specific diagnostics pub enum NonHaltingDiagnostic { - CreatedPointerTag(NonZeroU64, Option<(AllocId, AllocRange)>), + /// (new_tag, new_kind, (alloc_id, base_offset, orig_tag)) + /// + /// new_kind is `None` for base tags. + CreatedPointerTag(NonZeroU64, Option, Option<(AllocId, AllocRange, ProvenanceExtra)>), /// This `Item` was popped from the borrow stack, either due to an access with the given tag or /// a deallocation when the second argument is `None`. PoppedPointerTag(Item, Option<(ProvenanceExtra, AccessKind)>), @@ -376,7 +379,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { MiriInterpCx::generate_stacktrace_from_stack(self.threads.active_thread_stack()); let (stacktrace, _was_pruned) = prune_stacktrace(stacktrace, self); - let (title, diag_level) = match e { + let (title, diag_level) = match &e { RejectedIsolatedOp(_) => ("operation rejected by isolation", DiagLevel::Warning), Int2Ptr { .. } => ("integer-to-pointer cast", DiagLevel::Warning), CreatedPointerTag(..) @@ -388,10 +391,13 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { | WeakMemoryOutdatedLoad => ("tracking was triggered", DiagLevel::Note), }; - let msg = match e { - CreatedPointerTag(tag, None) => format!("created tag {tag:?}"), - CreatedPointerTag(tag, Some((alloc_id, range))) => - format!("created tag {tag:?} at {alloc_id:?}{range:?}"), + let msg = match &e { + CreatedPointerTag(tag, None, _) => format!("created base tag {tag:?}"), + CreatedPointerTag(tag, Some(kind), None) => format!("created {tag:?} for {kind}"), + CreatedPointerTag(tag, Some(kind), Some((alloc_id, range, orig_tag))) => + format!( + "created tag {tag:?} for {kind} at {alloc_id:?}{range:?} derived from {orig_tag:?}" + ), PoppedPointerTag(item, tag) => match tag { None => format!("popped tracked tag for item {item:?} due to deallocation",), @@ -418,7 +424,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { format!("weak memory emulation: outdated value returned from load"), }; - let notes = match e { + let notes = match &e { ProgressReport { block_count } => { // It is important that each progress report is slightly different, since // identical diagnostics are being deduplicated. @@ -427,7 +433,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { _ => vec![], }; - let helps = match e { + let helps = match &e { Int2Ptr { details: true } => vec![ ( diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index f7f4b1357f106..429c6eb8ef555 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -5,6 +5,7 @@ use log::trace; use std::cell::RefCell; use std::cmp; use std::fmt; +use std::fmt::Write; use std::num::NonZeroU64; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -203,7 +204,7 @@ impl GlobalStateInner { self.base_ptr_tags.get(&id).copied().unwrap_or_else(|| { let tag = self.new_ptr(); if self.tracked_pointer_tags.contains(&tag) { - machine.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(tag.0, None)); + machine.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag(tag.0, None, None)); } trace!("New allocation {:?} has base tag {:?}", id, tag); self.base_ptr_tags.try_insert(id, tag).unwrap(); @@ -674,10 +675,26 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<' loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag -> InterpResult<'tcx> { let global = this.machine.stacked_borrows.as_ref().unwrap().borrow(); + let ty = place.layout.ty; if global.tracked_pointer_tags.contains(&new_tag) { + let mut kind_str = format!("{kind}"); + match kind { + RefKind::Unique { two_phase: false } + if !ty.is_unpin(this.tcx.at(DUMMY_SP), this.param_env()) => + { + write!(kind_str, " (!Unpin pointee type {ty})").unwrap() + }, + RefKind::Shared + if !ty.is_freeze(this.tcx.at(DUMMY_SP), this.param_env()) => + { + write!(kind_str, " (!Freeze pointee type {ty})").unwrap() + }, + _ => write!(kind_str, " (pointee type {ty})").unwrap(), + }; this.emit_diagnostic(NonHaltingDiagnostic::CreatedPointerTag( new_tag.0, - loc.map(|(alloc_id, base_offset, _)| (alloc_id, alloc_range(base_offset, size))), + Some(kind_str), + loc.map(|(alloc_id, base_offset, orig_tag)| (alloc_id, alloc_range(base_offset, size), orig_tag)), )); } drop(global); // don't hold that reference any longer than we have to From 90d566cb8d59f340ab3e19806b5eca46a1b4b499 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 24 Sep 2022 14:20:22 -0400 Subject: [PATCH 22/28] Expand VisitMachineValues to cover more pointers in the interpreter --- src/concurrency/range_object_map.rs | 4 ++ src/concurrency/thread.rs | 78 +++++++++++++++++++---------- src/concurrency/weak_memory.rs | 13 +++++ src/machine.rs | 40 +++++++++++++-- src/shims/env.rs | 14 ++++++ src/shims/panic.rs | 7 +++ src/shims/unix/fs.rs | 8 +++ src/stacked_borrows/mod.rs | 2 +- src/stacked_borrows/stack.rs | 7 ++- src/tag_gc.rs | 16 ++++++ 10 files changed, 156 insertions(+), 33 deletions(-) diff --git a/src/concurrency/range_object_map.rs b/src/concurrency/range_object_map.rs index 50d3f8c9b20ea..dfe2e9f05dafd 100644 --- a/src/concurrency/range_object_map.rs +++ b/src/concurrency/range_object_map.rs @@ -132,6 +132,10 @@ impl RangeObjectMap { pub fn remove_from_pos(&mut self, pos: Position) { self.v.remove(pos); } + + pub fn iter(&self) -> impl Iterator { + self.v.iter().map(|e| &e.data) + } } impl Index for RangeObjectMap { diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index a9d144eff54ab..7b91f8c223ab6 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -181,6 +181,41 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> { } } +impl VisitMachineValues for Thread<'_, '_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + let Thread { panic_payload, last_error, stack, .. } = self; + + if let Some(payload) = panic_payload { + visit(&Operand::Immediate(Immediate::Scalar(*payload))) + } + if let Some(error) = last_error { + visit(&Operand::Indirect(**error)) + } + for frame in stack { + frame.visit_machine_values(visit) + } + } +} + +impl VisitMachineValues for Frame<'_, '_, Provenance, FrameData<'_>> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + let Frame { return_place, locals, extra, .. } = self; + + // Return place. + if let Place::Ptr(mplace) = **return_place { + visit(&Operand::Indirect(mplace)); + } + // Locals. + for local in locals.iter() { + if let LocalValue::Live(value) = &local.value { + visit(value); + } + } + + extra.visit_machine_values(visit); + } +} + /// A specific moment in time. #[derive(Debug)] pub enum Time { @@ -253,6 +288,22 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> { } } +impl VisitMachineValues for ThreadManager<'_, '_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + let ThreadManager { threads, thread_local_alloc_ids, .. } = self; + + for thread in threads { + thread.visit_machine_values(visit); + } + for ptr in thread_local_alloc_ids.borrow().values().copied() { + let ptr: Pointer> = ptr.into(); + visit(&Operand::Indirect(MemPlace::from_ptr(ptr))); + } + // FIXME: Do we need to do something for TimeoutCallback? That's a Box, not sure what + // to do. + } +} + impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { pub(crate) fn init(ecx: &mut MiriInterpCx<'mir, 'tcx>) { if ecx.tcx.sess.target.os.as_ref() != "windows" { @@ -625,33 +676,6 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { } } -impl VisitMachineValues for ThreadManager<'_, '_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - // FIXME some other fields also contain machine values - let ThreadManager { threads, .. } = self; - - for thread in threads { - // FIXME: implement VisitMachineValues for `Thread` and `Frame` instead. - // In particular we need to visit the `last_error` and `catch_unwind` fields. - if let Some(payload) = thread.panic_payload { - visit(&Operand::Immediate(Immediate::Scalar(payload))) - } - for frame in &thread.stack { - // Return place. - if let Place::Ptr(mplace) = *frame.return_place { - visit(&Operand::Indirect(mplace)); - } - // Locals. - for local in frame.locals.iter() { - if let LocalValue::Live(value) = &local.value { - visit(value); - } - } - } - } - } -} - // Public interface to thread management. impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { diff --git a/src/concurrency/weak_memory.rs b/src/concurrency/weak_memory.rs index bac403e9ec7b1..aa4e5add5031c 100644 --- a/src/concurrency/weak_memory.rs +++ b/src/concurrency/weak_memory.rs @@ -108,6 +108,19 @@ pub struct StoreBufferAlloc { store_buffers: RefCell>, } +impl StoreBufferAlloc { + pub fn iter(&self, mut visitor: impl FnMut(&Scalar)) { + for val in self + .store_buffers + .borrow() + .iter() + .flat_map(|buf| buf.buffer.iter().map(|element| &element.val)) + { + visitor(val) + } + } +} + #[derive(Debug, Clone, PartialEq, Eq)] pub(super) struct StoreBuffer { // Stores to this location in modification order diff --git a/src/machine.rs b/src/machine.rs index 03df78c1af715..6a06df2a16b34 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -63,6 +63,16 @@ impl<'tcx> std::fmt::Debug for FrameData<'tcx> { } } +impl VisitMachineValues for FrameData<'_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + let FrameData { catch_unwind, .. } = self; + + if let Some(catch_unwind) = catch_unwind { + catch_unwind.visit_machine_values(visit); + } + } +} + /// Extra memory kinds #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum MiriMemoryKind { @@ -593,12 +603,36 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { impl VisitMachineValues for MiriMachine<'_, '_> { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - // FIXME: visit the missing fields: env vars, weak mem, the MemPlace fields in the machine, - // DirHandler, extern_statics, the Stacked Borrows base pointers; maybe more. - let MiriMachine { threads, tls, .. } = self; + let MiriMachine { + threads, + tls, + env_vars, + argc, + argv, + cmd_line, + extern_statics, + dir_handler, + .. + } = self; threads.visit_machine_values(visit); tls.visit_machine_values(visit); + env_vars.visit_machine_values(visit); + dir_handler.visit_machine_values(visit); + + if let Some(argc) = argc { + visit(&Operand::Indirect(*argc)); + } + if let Some(argv) = argv { + visit(&Operand::Indirect(*argv)); + } + if let Some(cmd_line) = cmd_line { + visit(&Operand::Indirect(*cmd_line)); + } + for ptr in extern_statics.values().copied() { + let ptr: Pointer> = ptr.into(); + visit(&Operand::Indirect(MemPlace::from_ptr(ptr))); + } } } diff --git a/src/shims/env.rs b/src/shims/env.rs index 95051c998e5fd..ad2d2eaab34f5 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -36,6 +36,20 @@ pub struct EnvVars<'tcx> { pub(crate) environ: Option>, } +impl VisitMachineValues for EnvVars<'_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + let EnvVars { map, environ } = self; + + for ptr in map.values() { + visit(&Operand::Indirect(MemPlace::from_ptr(*ptr))); + } + + if let Some(env) = environ { + visit(&Operand::Indirect(**env)); + } + } +} + impl<'tcx> EnvVars<'tcx> { pub(crate) fn init<'mir>( ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>, diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 2e8245acf4a68..dd6e2d53b4e8c 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -35,6 +35,13 @@ pub struct CatchUnwindData<'tcx> { ret: mir::BasicBlock, } +impl VisitMachineValues for CatchUnwindData<'_> { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + visit(&Operand::Indirect(MemPlace::from_ptr(self.catch_fn))); + visit(&Operand::Immediate(Immediate::Scalar(self.data))); + } +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Handles the special `miri_start_panic` intrinsic, which is called diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 8464c4589ed5d..576e12d34757f 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -462,6 +462,14 @@ impl Default for DirHandler { } } +impl VisitMachineValues for DirHandler { + fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + for dir in self.streams.values() { + visit(&Operand::Indirect(MemPlace::from_ptr(dir.entry))); + } + } +} + fn maybe_sync_file( file: &File, writable: bool, diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index f7f4b1357f106..956f936dbcad8 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -79,7 +79,7 @@ pub struct Stacks { /// Stores past operations on this allocation history: AllocHistory, /// The set of tags that have been exposed inside this allocation. - exposed_tags: FxHashSet, + pub exposed_tags: FxHashSet, /// Whether this memory has been modified since the last time the tag GC ran modified_since_last_gc: bool, } diff --git a/src/stacked_borrows/stack.rs b/src/stacked_borrows/stack.rs index 494ea08b56e48..eb30f023935b9 100644 --- a/src/stacked_borrows/stack.rs +++ b/src/stacked_borrows/stack.rs @@ -43,8 +43,11 @@ impl Stack { pub fn retain(&mut self, tags: &FxHashSet) { let mut first_removed = None; - let mut read_idx = 1; - let mut write_idx = 1; + // For stacks with a known bottom, we never consider removing the bottom-most tag, because + // that is the base tag which exists whether or not there are any pointers to the + // allocation. + let mut read_idx = usize::from(self.unknown_bottom.is_none()); + let mut write_idx = read_idx; while read_idx < self.borrows.len() { let left = self.borrows[read_idx - 1]; let this = self.borrows[read_idx]; diff --git a/src/tag_gc.rs b/src/tag_gc.rs index 0bfc81ce01233..9378cc1e9207d 100644 --- a/src/tag_gc.rs +++ b/src/tag_gc.rs @@ -71,6 +71,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { tags.insert(*sb); } } + let stacks = alloc + .extra + .stacked_borrows + .as_ref() + .expect("we should not even enter the GC if Stacked Borrows is disabled"); + tags.extend(&stacks.borrow().exposed_tags); + + if let Some(store_buffers) = alloc.extra.weak_memory.as_ref() { + store_buffers.iter(|val| { + if let Scalar::Ptr(ptr, _) = val { + if let Provenance::Concrete { sb, .. } = ptr.provenance { + tags.insert(sb); + } + } + }); + } }, ); From 4f688152536ea557d85be5c1036752b7aaaa39f1 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 26 Sep 2022 16:07:32 -0400 Subject: [PATCH 23/28] A bit of cleanup --- src/concurrency/thread.rs | 23 ++++++++++++++++++++--- src/machine.rs | 2 +- src/shims/panic.rs | 5 +++-- src/shims/unix/fs.rs | 4 +++- src/stacked_borrows/stack.rs | 2 +- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 7b91f8c223ab6..1b05088b3d54e 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -183,7 +183,8 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> { impl VisitMachineValues for Thread<'_, '_> { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - let Thread { panic_payload, last_error, stack, .. } = self; + let Thread { panic_payload, last_error, stack, state: _, thread_name: _, join_status: _ } = + self; if let Some(payload) = panic_payload { visit(&Operand::Immediate(Immediate::Scalar(*payload))) @@ -199,7 +200,16 @@ impl VisitMachineValues for Thread<'_, '_> { impl VisitMachineValues for Frame<'_, '_, Provenance, FrameData<'_>> { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - let Frame { return_place, locals, extra, .. } = self; + let Frame { + return_place, + locals, + extra, + body: _, + instance: _, + return_to_block: _, + loc: _, + .. + } = self; // Return place. if let Place::Ptr(mplace) = **return_place { @@ -290,7 +300,14 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> { impl VisitMachineValues for ThreadManager<'_, '_> { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - let ThreadManager { threads, thread_local_alloc_ids, .. } = self; + let ThreadManager { + threads, + thread_local_alloc_ids, + active_thread: _, + yield_active_thread: _, + sync: _, + timeout_callbacks: _, + } = self; for thread in threads { thread.visit_machine_values(visit); diff --git a/src/machine.rs b/src/machine.rs index 6a06df2a16b34..35d5c0d9a8744 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -65,7 +65,7 @@ impl<'tcx> std::fmt::Debug for FrameData<'tcx> { impl VisitMachineValues for FrameData<'_> { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - let FrameData { catch_unwind, .. } = self; + let FrameData { catch_unwind, stacked_borrows: _, timing: _ } = self; if let Some(catch_unwind) = catch_unwind { catch_unwind.visit_machine_values(visit); diff --git a/src/shims/panic.rs b/src/shims/panic.rs index dd6e2d53b4e8c..be14892f69681 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -37,8 +37,9 @@ pub struct CatchUnwindData<'tcx> { impl VisitMachineValues for CatchUnwindData<'_> { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - visit(&Operand::Indirect(MemPlace::from_ptr(self.catch_fn))); - visit(&Operand::Immediate(Immediate::Scalar(self.data))); + let CatchUnwindData { catch_fn, data, dest: _, ret: _ } = self; + visit(&Operand::Indirect(MemPlace::from_ptr(*catch_fn))); + visit(&Operand::Immediate(Immediate::Scalar(*data))); } } diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 576e12d34757f..59d24e00dc1ae 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -464,7 +464,9 @@ impl Default for DirHandler { impl VisitMachineValues for DirHandler { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { - for dir in self.streams.values() { + let DirHandler { streams, next_id: _ } = self; + + for dir in streams.values() { visit(&Operand::Indirect(MemPlace::from_ptr(dir.entry))); } } diff --git a/src/stacked_borrows/stack.rs b/src/stacked_borrows/stack.rs index eb30f023935b9..57de1c21c8b2d 100644 --- a/src/stacked_borrows/stack.rs +++ b/src/stacked_borrows/stack.rs @@ -46,7 +46,7 @@ impl Stack { // For stacks with a known bottom, we never consider removing the bottom-most tag, because // that is the base tag which exists whether or not there are any pointers to the // allocation. - let mut read_idx = usize::from(self.unknown_bottom.is_none()); + let mut read_idx = if self.unknown_bottom.is_some() { 0 } else { 1 }; let mut write_idx = read_idx; while read_idx < self.borrows.len() { let left = self.borrows[read_idx - 1]; From d1563b0b1a8b20fe9526fc498b5d8a7b9bbaa79c Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 26 Sep 2022 18:06:20 -0400 Subject: [PATCH 24/28] Use VisitProvenance to factor allocation visiting better --- src/concurrency/weak_memory.rs | 10 +++++++--- src/lib.rs | 2 +- src/stacked_borrows/mod.rs | 10 +++++++++- src/tag_gc.rs | 28 +++++++++++++++------------- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/concurrency/weak_memory.rs b/src/concurrency/weak_memory.rs index aa4e5add5031c..becd61f4fea66 100644 --- a/src/concurrency/weak_memory.rs +++ b/src/concurrency/weak_memory.rs @@ -108,15 +108,19 @@ pub struct StoreBufferAlloc { store_buffers: RefCell>, } -impl StoreBufferAlloc { - pub fn iter(&self, mut visitor: impl FnMut(&Scalar)) { +impl VisitProvenance for StoreBufferAlloc { + fn visit_provenance(&self, visitor: &mut impl FnMut(SbTag)) { for val in self .store_buffers .borrow() .iter() .flat_map(|buf| buf.buffer.iter().map(|element| &element.val)) { - visitor(val) + if let Scalar::Ptr(ptr, _) = val { + if let Provenance::Concrete { sb, .. } = ptr.provenance { + visitor(sb); + } + } } } } diff --git a/src/lib.rs b/src/lib.rs index bf4e21319b526..e60e1f15b5f89 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,7 @@ pub use crate::range_map::RangeMap; pub use crate::stacked_borrows::{ CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks, }; -pub use crate::tag_gc::{EvalContextExt as _, VisitMachineValues}; +pub use crate::tag_gc::{EvalContextExt as _, VisitMachineValues, VisitProvenance}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index 956f936dbcad8..ab90e35844997 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -79,7 +79,7 @@ pub struct Stacks { /// Stores past operations on this allocation history: AllocHistory, /// The set of tags that have been exposed inside this allocation. - pub exposed_tags: FxHashSet, + exposed_tags: FxHashSet, /// Whether this memory has been modified since the last time the tag GC ran modified_since_last_gc: bool, } @@ -513,6 +513,14 @@ impl Stacks { } } +impl VisitProvenance for Stacks { + fn visit_provenance(&self, visit: &mut impl FnMut(SbTag)) { + for tag in self.exposed_tags.iter().copied() { + visit(tag); + } + } +} + /// Map per-stack operations to higher-level per-location-range operations. impl<'tcx> Stacks { /// Creates a new stack with an initial tag. For diagnostic purposes, we also need to know diff --git a/src/tag_gc.rs b/src/tag_gc.rs index 9378cc1e9207d..0a8d5d00cfb63 100644 --- a/src/tag_gc.rs +++ b/src/tag_gc.rs @@ -6,6 +6,10 @@ pub trait VisitMachineValues { fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)); } +pub trait VisitProvenance { + fn visit_provenance(&self, visit: &mut impl FnMut(SbTag)); +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { /// Generic GC helper to visit everything that can store a value. The `acc` offers some chance to @@ -46,6 +50,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { } }; + let visit_provenance = |tags: &mut FxHashSet, tag: SbTag| { + tags.insert(tag); + }; + this.visit_all_machine_values( &mut tags, |tags, op| { @@ -71,21 +79,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { tags.insert(*sb); } } - let stacks = alloc - .extra - .stacked_borrows - .as_ref() - .expect("we should not even enter the GC if Stacked Borrows is disabled"); - tags.extend(&stacks.borrow().exposed_tags); + + let stacks = + alloc.extra.stacked_borrows.as_ref().expect( + "we should not even enter the tag GC if Stacked Borrows is disabled", + ); + stacks.borrow().visit_provenance(&mut |tag| visit_provenance(tags, tag)); if let Some(store_buffers) = alloc.extra.weak_memory.as_ref() { - store_buffers.iter(|val| { - if let Scalar::Ptr(ptr, _) = val { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - } - } - }); + store_buffers.visit_provenance(&mut |tag| visit_provenance(tags, tag)); } }, ); From eb2a36b01801316a74a2419aecfe6308ba7c6b5d Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 26 Sep 2022 19:50:50 -0400 Subject: [PATCH 25/28] Use static dispatch in the visitor --- src/concurrency/thread.rs | 17 ++-- src/concurrency/weak_memory.rs | 10 +- src/lib.rs | 2 +- src/machine.rs | 27 ++++-- src/shims/env.rs | 7 +- src/shims/panic.rs | 6 +- src/shims/tls.rs | 6 +- src/shims/unix/fs.rs | 4 +- src/stacked_borrows/mod.rs | 6 +- src/tag_gc.rs | 168 ++++++++++++++++++++------------- 10 files changed, 148 insertions(+), 105 deletions(-) diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 1b05088b3d54e..01ae4320f3bbb 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -182,15 +182,15 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> { } impl VisitMachineValues for Thread<'_, '_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let Thread { panic_payload, last_error, stack, state: _, thread_name: _, join_status: _ } = self; if let Some(payload) = panic_payload { - visit(&Operand::Immediate(Immediate::Scalar(*payload))) + visit.visit(*payload); } if let Some(error) = last_error { - visit(&Operand::Indirect(**error)) + visit.visit(**error); } for frame in stack { frame.visit_machine_values(visit) @@ -199,7 +199,7 @@ impl VisitMachineValues for Thread<'_, '_> { } impl VisitMachineValues for Frame<'_, '_, Provenance, FrameData<'_>> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let Frame { return_place, locals, @@ -213,12 +213,12 @@ impl VisitMachineValues for Frame<'_, '_, Provenance, FrameData<'_>> { // Return place. if let Place::Ptr(mplace) = **return_place { - visit(&Operand::Indirect(mplace)); + visit.visit(mplace); } // Locals. for local in locals.iter() { if let LocalValue::Live(value) = &local.value { - visit(value); + visit.visit(value); } } @@ -299,7 +299,7 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> { } impl VisitMachineValues for ThreadManager<'_, '_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let ThreadManager { threads, thread_local_alloc_ids, @@ -313,8 +313,7 @@ impl VisitMachineValues for ThreadManager<'_, '_> { thread.visit_machine_values(visit); } for ptr in thread_local_alloc_ids.borrow().values().copied() { - let ptr: Pointer> = ptr.into(); - visit(&Operand::Indirect(MemPlace::from_ptr(ptr))); + visit.visit(ptr); } // FIXME: Do we need to do something for TimeoutCallback? That's a Box, not sure what // to do. diff --git a/src/concurrency/weak_memory.rs b/src/concurrency/weak_memory.rs index becd61f4fea66..15c6c8e9c0e46 100644 --- a/src/concurrency/weak_memory.rs +++ b/src/concurrency/weak_memory.rs @@ -108,19 +108,15 @@ pub struct StoreBufferAlloc { store_buffers: RefCell>, } -impl VisitProvenance for StoreBufferAlloc { - fn visit_provenance(&self, visitor: &mut impl FnMut(SbTag)) { +impl VisitMachineValues for StoreBufferAlloc { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { for val in self .store_buffers .borrow() .iter() .flat_map(|buf| buf.buffer.iter().map(|element| &element.val)) { - if let Scalar::Ptr(ptr, _) = val { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - visitor(sb); - } - } + visit.visit(val); } } } diff --git a/src/lib.rs b/src/lib.rs index e60e1f15b5f89..245bdc51a8a75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,7 @@ pub use crate::range_map::RangeMap; pub use crate::stacked_borrows::{ CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks, }; -pub use crate::tag_gc::{EvalContextExt as _, VisitMachineValues, VisitProvenance}; +pub use crate::tag_gc::{EvalContextExt as _, ProvenanceVisitor, VisitMachineValues}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/machine.rs b/src/machine.rs index 35d5c0d9a8744..523aad22aa5aa 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -64,7 +64,7 @@ impl<'tcx> std::fmt::Debug for FrameData<'tcx> { } impl VisitMachineValues for FrameData<'_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let FrameData { catch_unwind, stacked_borrows: _, timing: _ } = self; if let Some(catch_unwind) = catch_unwind { @@ -261,6 +261,20 @@ pub struct AllocExtra { pub weak_memory: Option, } +impl VisitMachineValues for AllocExtra { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { + let AllocExtra { stacked_borrows, data_race: _, weak_memory } = self; + + if let Some(stacked_borrows) = stacked_borrows { + stacked_borrows.borrow().visit_machine_values(visit); + } + + if let Some(weak_memory) = weak_memory { + weak_memory.visit_machine_values(visit); + } + } +} + /// Precomputed layouts of primitive types pub struct PrimitiveLayouts<'tcx> { pub unit: TyAndLayout<'tcx>, @@ -602,7 +616,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { } impl VisitMachineValues for MiriMachine<'_, '_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let MiriMachine { threads, tls, @@ -621,17 +635,16 @@ impl VisitMachineValues for MiriMachine<'_, '_> { dir_handler.visit_machine_values(visit); if let Some(argc) = argc { - visit(&Operand::Indirect(*argc)); + visit.visit(argc); } if let Some(argv) = argv { - visit(&Operand::Indirect(*argv)); + visit.visit(argv); } if let Some(cmd_line) = cmd_line { - visit(&Operand::Indirect(*cmd_line)); + visit.visit(cmd_line); } for ptr in extern_statics.values().copied() { - let ptr: Pointer> = ptr.into(); - visit(&Operand::Indirect(MemPlace::from_ptr(ptr))); + visit.visit(ptr); } } } diff --git a/src/shims/env.rs b/src/shims/env.rs index ad2d2eaab34f5..d922014c38352 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -37,15 +37,14 @@ pub struct EnvVars<'tcx> { } impl VisitMachineValues for EnvVars<'_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let EnvVars { map, environ } = self; for ptr in map.values() { - visit(&Operand::Indirect(MemPlace::from_ptr(*ptr))); + visit.visit(*ptr); } - if let Some(env) = environ { - visit(&Operand::Indirect(**env)); + visit.visit(**env); } } } diff --git a/src/shims/panic.rs b/src/shims/panic.rs index be14892f69681..0d681d3e09b59 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -36,10 +36,10 @@ pub struct CatchUnwindData<'tcx> { } impl VisitMachineValues for CatchUnwindData<'_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let CatchUnwindData { catch_fn, data, dest: _, ret: _ } = self; - visit(&Operand::Indirect(MemPlace::from_ptr(*catch_fn))); - visit(&Operand::Immediate(Immediate::Scalar(*data))); + visit.visit(catch_fn); + visit.visit(data); } } diff --git a/src/shims/tls.rs b/src/shims/tls.rs index d1cee307d774c..568eb6fa91071 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -236,14 +236,14 @@ impl<'tcx> TlsData<'tcx> { } impl VisitMachineValues for TlsData<'_> { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let TlsData { keys, macos_thread_dtors, next_key: _, dtors_running: _ } = self; for scalar in keys.values().flat_map(|v| v.data.values()) { - visit(&Operand::Immediate(Immediate::Scalar(*scalar))); + visit.visit(scalar); } for (_, scalar) in macos_thread_dtors.values() { - visit(&Operand::Immediate(Immediate::Scalar(*scalar))); + visit.visit(scalar); } } } diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 59d24e00dc1ae..5024b2ab45f02 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -463,11 +463,11 @@ impl Default for DirHandler { } impl VisitMachineValues for DirHandler { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)) { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { let DirHandler { streams, next_id: _ } = self; for dir in streams.values() { - visit(&Operand::Indirect(MemPlace::from_ptr(dir.entry))); + visit.visit(dir.entry); } } } diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index ab90e35844997..b40358e2c15a3 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -513,10 +513,10 @@ impl Stacks { } } -impl VisitProvenance for Stacks { - fn visit_provenance(&self, visit: &mut impl FnMut(SbTag)) { +impl VisitMachineValues for Stacks { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { for tag in self.exposed_tags.iter().copied() { - visit(tag); + visit.visit(tag); } } } diff --git a/src/tag_gc.rs b/src/tag_gc.rs index 0a8d5d00cfb63..e2273f055dd9b 100644 --- a/src/tag_gc.rs +++ b/src/tag_gc.rs @@ -3,34 +3,120 @@ use rustc_data_structures::fx::FxHashSet; use crate::*; pub trait VisitMachineValues { - fn visit_machine_values(&self, visit: &mut impl FnMut(&Operand)); + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor); } -pub trait VisitProvenance { - fn visit_provenance(&self, visit: &mut impl FnMut(SbTag)); +pub trait MachineValue { + fn visit_provenance(&self, tags: &mut FxHashSet); +} + +pub struct ProvenanceVisitor { + tags: FxHashSet, +} + +impl ProvenanceVisitor { + pub fn visit(&mut self, v: V) + where + V: MachineValue, + { + v.visit_provenance(&mut self.tags); + } +} + +impl MachineValue for &T { + fn visit_provenance(&self, tags: &mut FxHashSet) { + (**self).visit_provenance(tags); + } +} + +impl MachineValue for Operand { + fn visit_provenance(&self, tags: &mut FxHashSet) { + match self { + Operand::Immediate(Immediate::Scalar(s)) => { + s.visit_provenance(tags); + } + Operand::Immediate(Immediate::ScalarPair(s1, s2)) => { + s1.visit_provenance(tags); + s2.visit_provenance(tags); + } + Operand::Immediate(Immediate::Uninit) => {} + Operand::Indirect(p) => { + p.visit_provenance(tags); + } + } + } +} + +impl MachineValue for Scalar { + fn visit_provenance(&self, tags: &mut FxHashSet) { + if let Scalar::Ptr(ptr, _) = self { + if let Provenance::Concrete { sb, .. } = ptr.provenance { + tags.insert(sb); + } + } + } +} + +impl MachineValue for MemPlace { + fn visit_provenance(&self, tags: &mut FxHashSet) { + if let Some(Provenance::Concrete { sb, .. }) = self.ptr.provenance { + tags.insert(sb); + } + } +} + +impl MachineValue for SbTag { + fn visit_provenance(&self, tags: &mut FxHashSet) { + tags.insert(*self); + } +} + +impl MachineValue for Pointer { + fn visit_provenance(&self, tags: &mut FxHashSet) { + let (prov, _offset) = self.into_parts(); + if let Provenance::Concrete { sb, .. } = prov { + tags.insert(sb); + } + } +} + +impl MachineValue for Pointer> { + fn visit_provenance(&self, tags: &mut FxHashSet) { + let (prov, _offset) = self.into_parts(); + if let Some(Provenance::Concrete { sb, .. }) = prov { + tags.insert(sb); + } + } +} + +impl VisitMachineValues for Allocation { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { + for (_size, prov) in self.provenance().iter() { + if let Provenance::Concrete { sb, .. } = prov { + visit.visit(*sb); + } + } + + self.extra.visit_machine_values(visit); + } } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { - /// Generic GC helper to visit everything that can store a value. The `acc` offers some chance to - /// accumulate everything. - fn visit_all_machine_values( - &self, - acc: &mut T, - mut visit_operand: impl FnMut(&mut T, &Operand), - mut visit_alloc: impl FnMut(&mut T, &Allocation), - ) { + /// GC helper to visit everything that can store provenance. The `ProvenanceVisitor` knows how + /// to extract provenance from the interpreter data types. + fn visit_all_machine_values(&self, acc: &mut ProvenanceVisitor) { let this = self.eval_context_ref(); // Memory. this.memory.alloc_map().iter(|it| { for (_id, (_kind, alloc)) in it { - visit_alloc(acc, alloc); + alloc.visit_machine_values(acc); } }); // And all the other machine values. - this.machine.visit_machine_values(&mut |op| visit_operand(acc, op)); + this.machine.visit_machine_values(acc); } fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { @@ -40,59 +126,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { return Ok(()); } - let mut tags = FxHashSet::default(); - - let visit_scalar = |tags: &mut FxHashSet, s: &Scalar| { - if let Scalar::Ptr(ptr, _) = s { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); - } - } - }; - - let visit_provenance = |tags: &mut FxHashSet, tag: SbTag| { - tags.insert(tag); - }; - - this.visit_all_machine_values( - &mut tags, - |tags, op| { - match op { - Operand::Immediate(Immediate::Scalar(s)) => { - visit_scalar(tags, s); - } - Operand::Immediate(Immediate::ScalarPair(s1, s2)) => { - visit_scalar(tags, s1); - visit_scalar(tags, s2); - } - Operand::Immediate(Immediate::Uninit) => {} - Operand::Indirect(MemPlace { ptr, .. }) => { - if let Some(Provenance::Concrete { sb, .. }) = ptr.provenance { - tags.insert(sb); - } - } - } - }, - |tags, alloc| { - for (_size, prov) in alloc.provenance().iter() { - if let Provenance::Concrete { sb, .. } = prov { - tags.insert(*sb); - } - } - - let stacks = - alloc.extra.stacked_borrows.as_ref().expect( - "we should not even enter the tag GC if Stacked Borrows is disabled", - ); - stacks.borrow().visit_provenance(&mut |tag| visit_provenance(tags, tag)); - - if let Some(store_buffers) = alloc.extra.weak_memory.as_ref() { - store_buffers.visit_provenance(&mut |tag| visit_provenance(tags, tag)); - } - }, - ); - - self.remove_unreachable_tags(tags); + let mut visitor = ProvenanceVisitor { tags: FxHashSet::default() }; + this.visit_all_machine_values(&mut visitor); + self.remove_unreachable_tags(visitor.tags); Ok(()) } From 8686067bb56241703b77b683adb84f1016c95ae9 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Mon, 26 Sep 2022 21:48:18 -0400 Subject: [PATCH 26/28] Please help, where is this lifetime bound coming from --- src/concurrency/thread.rs | 16 ++++++------ src/shims/time.rs | 26 +++++++++++++------ src/shims/unix/linux/sync.rs | 38 ++++++++++++++++++++------- src/shims/unix/sync.rs | 50 +++++++++++++++++++++++++----------- 4 files changed, 90 insertions(+), 40 deletions(-) diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 01ae4320f3bbb..3c5a6786bd1c8 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -32,9 +32,9 @@ pub enum SchedulingAction { /// Timeout callbacks can be created by synchronization primitives to tell the /// scheduler that they should be called once some period of time passes. -type TimeoutCallback<'mir, 'tcx> = Box< - dyn FnOnce(&mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx> + 'tcx, ->; +pub trait TimeoutCallback<'mir, 'tcx>: VisitMachineValues + 'tcx { + fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>; +} /// A thread identifier. #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] @@ -252,7 +252,7 @@ struct TimeoutCallbackInfo<'mir, 'tcx> { /// The callback should be called no earlier than this time. call_time: Time, /// The called function. - callback: TimeoutCallback<'mir, 'tcx>, + callback: Box>, } impl<'mir, 'tcx> std::fmt::Debug for TimeoutCallbackInfo<'mir, 'tcx> { @@ -542,7 +542,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { &mut self, thread: ThreadId, call_time: Time, - callback: TimeoutCallback<'mir, 'tcx>, + callback: Box>, ) { self.timeout_callbacks .try_insert(thread, TimeoutCallbackInfo { call_time, callback }) @@ -558,7 +558,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { fn get_ready_callback( &mut self, clock: &Clock, - ) -> Option<(ThreadId, TimeoutCallback<'mir, 'tcx>)> { + ) -> Option<(ThreadId, Box>)> { // We iterate over all threads in the order of their indices because // this allows us to have a deterministic scheduler. for thread in self.threads.indices() { @@ -931,7 +931,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, thread: ThreadId, call_time: Time, - callback: TimeoutCallback<'mir, 'tcx>, + callback: Box>, ) { let this = self.eval_context_mut(); if !this.machine.communicate() && matches!(call_time, Time::RealTime(..)) { @@ -970,7 +970,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // 2. Make the scheduler the only place that can change the active // thread. let old_thread = this.set_active_thread(thread); - callback(this)?; + callback.call(this)?; this.set_active_thread(old_thread); Ok(()) } diff --git a/src/shims/time.rs b/src/shims/time.rs index 24fe524539396..43792024e2c9d 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -1,5 +1,6 @@ use std::time::{Duration, SystemTime}; +use crate::concurrency::thread::TimeoutCallback; use crate::*; /// Returns the time elapsed between the provided time and the unix epoch as a `Duration`. @@ -218,10 +219,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(move |ecx| { - ecx.unblock_thread(active_thread); - Ok(()) - }), + Box::new(Callback { active_thread }), ); Ok(0) @@ -244,12 +242,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(move |ecx| { - ecx.unblock_thread(active_thread); - Ok(()) - }), + Box::new(Callback { active_thread }), ); Ok(()) } } + +struct Callback { + active_thread: ThreadId, +} + +impl VisitMachineValues for Callback { + fn visit_machine_values(&self, _visit: &mut ProvenanceVisitor) {} +} + +impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + ecx.unblock_thread(self.active_thread); + Ok(()) + } +} diff --git a/src/shims/unix/linux/sync.rs b/src/shims/unix/linux/sync.rs index 5a6ce28d25c9f..784fa12d18a2b 100644 --- a/src/shims/unix/linux/sync.rs +++ b/src/shims/unix/linux/sync.rs @@ -1,4 +1,4 @@ -use crate::concurrency::thread::Time; +use crate::concurrency::thread::{Time, TimeoutCallback}; use crate::*; use rustc_target::abi::{Align, Size}; use std::time::SystemTime; @@ -193,14 +193,7 @@ pub fn futex<'tcx>( this.register_timeout_callback( thread, timeout_time, - Box::new(move |this| { - this.unblock_thread(thread); - this.futex_remove_waiter(addr_usize, thread); - let etimedout = this.eval_libc("ETIMEDOUT")?; - this.set_last_error(etimedout)?; - this.write_scalar(Scalar::from_machine_isize(-1, this), &dest)?; - Ok(()) - }), + Box::new(Callback { thread, addr_usize, dest }), ); } } else { @@ -259,3 +252,30 @@ pub fn futex<'tcx>( Ok(()) } + +struct Callback<'tcx> { + thread: ThreadId, + addr_usize: u64, + dest: PlaceTy<'tcx, Provenance>, +} + +impl<'tcx> VisitMachineValues for Callback<'tcx> { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { + let Callback { thread: _, addr_usize: _, dest } = self; + if let Place::Ptr(place) = **dest { + visit.visit(place); + } + } +} + +impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + this.unblock_thread(self.thread); + this.futex_remove_waiter(self.addr_usize, self.thread); + let etimedout = this.eval_libc("ETIMEDOUT")?; + this.set_last_error(etimedout)?; + this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; + + Ok(()) + } +} diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs index 2e972a27ffebe..cdb3cdc4b9a59 100644 --- a/src/shims/unix/sync.rs +++ b/src/shims/unix/sync.rs @@ -3,7 +3,7 @@ use std::time::SystemTime; use rustc_hir::LangItem; use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty}; -use crate::concurrency::thread::Time; +use crate::concurrency::thread::{Time, TimeoutCallback}; use crate::*; // pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform. @@ -856,20 +856,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, timeout_time, - Box::new(move |ecx| { - // We are not waiting for the condvar any more, wait for the - // mutex instead. - reacquire_cond_mutex(ecx, active_thread, mutex_id)?; - - // Remove the thread from the conditional variable. - ecx.condvar_remove_waiter(id, active_thread); - - // Set the return value: we timed out. - let etimedout = ecx.eval_libc("ETIMEDOUT")?; - ecx.write_scalar(etimedout, &dest)?; - - Ok(()) - }), + Box::new(Callback { active_thread, mutex_id, id, dest }), ); Ok(()) @@ -898,6 +885,39 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } +struct Callback<'tcx> { + active_thread: ThreadId, + mutex_id: MutexId, + id: CondvarId, + dest: PlaceTy<'tcx, Provenance>, +} + +impl<'tcx> VisitMachineValues for Callback<'tcx> { + fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { + let Callback { active_thread: _, mutex_id: _, id: _, dest } = self; + if let Place::Ptr(place) = **dest { + visit.visit(place); + } + } +} + +impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + // We are not waiting for the condvar any more, wait for the + // mutex instead. + reacquire_cond_mutex(ecx, self.active_thread, self.mutex_id)?; + + // Remove the thread from the conditional variable. + ecx.condvar_remove_waiter(self.id, self.active_thread); + + // Set the return value: we timed out. + let etimedout = ecx.eval_libc("ETIMEDOUT")?; + ecx.write_scalar(etimedout, &self.dest)?; + + Ok(()) + } +} + fn layout_of_maybe_uninit<'tcx>(tcx: TyCtxtAt<'tcx>, param: Ty<'tcx>) -> TyAndLayout<'tcx> { let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None); let ty = tcx.bound_type_of(def_id).subst(*tcx, &[param.into()]); From e0a49154e4bcbea074ac974e3c141e9b12bd5c36 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Tue, 27 Sep 2022 05:40:12 -0400 Subject: [PATCH 27/28] Finish TimeoutCallback --- src/concurrency/thread.rs | 19 +++++++++++-------- src/shims/time.rs | 4 ++-- src/shims/unix/linux/sync.rs | 4 ++-- src/shims/unix/sync.rs | 4 ++-- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 3c5a6786bd1c8..5e6fcbde69ad9 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -32,10 +32,12 @@ pub enum SchedulingAction { /// Timeout callbacks can be created by synchronization primitives to tell the /// scheduler that they should be called once some period of time passes. -pub trait TimeoutCallback<'mir, 'tcx>: VisitMachineValues + 'tcx { +pub trait MachineCallback<'mir, 'tcx>: VisitMachineValues { fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>; } +type TimeoutCallback<'mir, 'tcx> = Box + 'tcx>; + /// A thread identifier. #[derive(Clone, Copy, Debug, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct ThreadId(u32); @@ -252,7 +254,7 @@ struct TimeoutCallbackInfo<'mir, 'tcx> { /// The callback should be called no earlier than this time. call_time: Time, /// The called function. - callback: Box>, + callback: TimeoutCallback<'mir, 'tcx>, } impl<'mir, 'tcx> std::fmt::Debug for TimeoutCallbackInfo<'mir, 'tcx> { @@ -303,10 +305,10 @@ impl VisitMachineValues for ThreadManager<'_, '_> { let ThreadManager { threads, thread_local_alloc_ids, + timeout_callbacks, active_thread: _, yield_active_thread: _, sync: _, - timeout_callbacks: _, } = self; for thread in threads { @@ -315,8 +317,9 @@ impl VisitMachineValues for ThreadManager<'_, '_> { for ptr in thread_local_alloc_ids.borrow().values().copied() { visit.visit(ptr); } - // FIXME: Do we need to do something for TimeoutCallback? That's a Box, not sure what - // to do. + for callback in timeout_callbacks.values() { + callback.callback.visit_machine_values(visit); + } } } @@ -542,7 +545,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { &mut self, thread: ThreadId, call_time: Time, - callback: Box>, + callback: TimeoutCallback<'mir, 'tcx>, ) { self.timeout_callbacks .try_insert(thread, TimeoutCallbackInfo { call_time, callback }) @@ -558,7 +561,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> { fn get_ready_callback( &mut self, clock: &Clock, - ) -> Option<(ThreadId, Box>)> { + ) -> Option<(ThreadId, TimeoutCallback<'mir, 'tcx>)> { // We iterate over all threads in the order of their indices because // this allows us to have a deterministic scheduler. for thread in self.threads.indices() { @@ -931,7 +934,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &mut self, thread: ThreadId, call_time: Time, - callback: Box>, + callback: TimeoutCallback<'mir, 'tcx>, ) { let this = self.eval_context_mut(); if !this.machine.communicate() && matches!(call_time, Time::RealTime(..)) { diff --git a/src/shims/time.rs b/src/shims/time.rs index 43792024e2c9d..05eff3dfd59e1 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -1,6 +1,6 @@ use std::time::{Duration, SystemTime}; -use crate::concurrency::thread::TimeoutCallback; +use crate::concurrency::thread::MachineCallback; use crate::*; /// Returns the time elapsed between the provided time and the unix epoch as a `Duration`. @@ -257,7 +257,7 @@ impl VisitMachineValues for Callback { fn visit_machine_values(&self, _visit: &mut ProvenanceVisitor) {} } -impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback { +impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback { fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { ecx.unblock_thread(self.active_thread); Ok(()) diff --git a/src/shims/unix/linux/sync.rs b/src/shims/unix/linux/sync.rs index 784fa12d18a2b..bbfb1c34db7d0 100644 --- a/src/shims/unix/linux/sync.rs +++ b/src/shims/unix/linux/sync.rs @@ -1,4 +1,4 @@ -use crate::concurrency::thread::{Time, TimeoutCallback}; +use crate::concurrency::thread::{MachineCallback, Time}; use crate::*; use rustc_target::abi::{Align, Size}; use std::time::SystemTime; @@ -268,7 +268,7 @@ impl<'tcx> VisitMachineValues for Callback<'tcx> { } } -impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> { +impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { this.unblock_thread(self.thread); this.futex_remove_waiter(self.addr_usize, self.thread); diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs index cdb3cdc4b9a59..72b71ada8e0cb 100644 --- a/src/shims/unix/sync.rs +++ b/src/shims/unix/sync.rs @@ -3,7 +3,7 @@ use std::time::SystemTime; use rustc_hir::LangItem; use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty}; -use crate::concurrency::thread::{Time, TimeoutCallback}; +use crate::concurrency::thread::{MachineCallback, Time}; use crate::*; // pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform. @@ -901,7 +901,7 @@ impl<'tcx> VisitMachineValues for Callback<'tcx> { } } -impl<'mir, 'tcx: 'mir> TimeoutCallback<'mir, 'tcx> for Callback<'tcx> { +impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { // We are not waiting for the condvar any more, wait for the // mutex instead. From d2552d28953a860c9a8a8a5ca8b749a145b262d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 2 Oct 2022 16:22:53 +0200 Subject: [PATCH 28/28] re-architect the tag visitor traits --- src/concurrency/data_race.rs | 12 +++ src/concurrency/thread.rs | 41 ++++---- src/concurrency/weak_memory.rs | 10 +- src/intptrcast.rs | 6 ++ src/lib.rs | 2 +- src/machine.rs | 93 +++++++++++------- src/shims/env.rs | 10 +- src/shims/panic.rs | 11 ++- src/shims/time.rs | 16 +-- src/shims/tls.rs | 8 +- src/shims/unix/fs.rs | 12 ++- src/shims/unix/linux/sync.rs | 52 +++++----- src/shims/unix/sync.rs | 64 ++++++------ src/stacked_borrows/mod.rs | 19 +++- src/tag_gc.rs | 172 ++++++++++++++++++++------------- 15 files changed, 306 insertions(+), 222 deletions(-) diff --git a/src/concurrency/data_race.rs b/src/concurrency/data_race.rs index 2e54ddaaba113..d0fc349f1acc3 100644 --- a/src/concurrency/data_race.rs +++ b/src/concurrency/data_race.rs @@ -696,6 +696,12 @@ pub struct VClockAlloc { alloc_ranges: RefCell>, } +impl VisitTags for VClockAlloc { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // No tags here. + } +} + impl VClockAlloc { /// Create a new data-race detector for newly allocated memory. pub fn new_allocation( @@ -1239,6 +1245,12 @@ pub struct GlobalState { pub track_outdated_loads: bool, } +impl VisitTags for GlobalState { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // We don't have any tags. + } +} + impl GlobalState { /// Create a new global state, setup with just thread-id=0 /// advanced to timestamp = 1. diff --git a/src/concurrency/thread.rs b/src/concurrency/thread.rs index 5e6fcbde69ad9..ec1da4138d448 100644 --- a/src/concurrency/thread.rs +++ b/src/concurrency/thread.rs @@ -32,7 +32,7 @@ pub enum SchedulingAction { /// Timeout callbacks can be created by synchronization primitives to tell the /// scheduler that they should be called once some period of time passes. -pub trait MachineCallback<'mir, 'tcx>: VisitMachineValues { +pub trait MachineCallback<'mir, 'tcx>: VisitTags { fn call(&self, ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>) -> InterpResult<'tcx>; } @@ -183,25 +183,21 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> { } } -impl VisitMachineValues for Thread<'_, '_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for Thread<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { let Thread { panic_payload, last_error, stack, state: _, thread_name: _, join_status: _ } = self; - if let Some(payload) = panic_payload { - visit.visit(*payload); - } - if let Some(error) = last_error { - visit.visit(**error); - } + panic_payload.visit_tags(visit); + last_error.visit_tags(visit); for frame in stack { - frame.visit_machine_values(visit) + frame.visit_tags(visit) } } } -impl VisitMachineValues for Frame<'_, '_, Provenance, FrameData<'_>> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for Frame<'_, '_, Provenance, FrameData<'_>> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { let Frame { return_place, locals, @@ -210,21 +206,20 @@ impl VisitMachineValues for Frame<'_, '_, Provenance, FrameData<'_>> { instance: _, return_to_block: _, loc: _, + // There are some private fields we cannot access; they contain no tags. .. } = self; // Return place. - if let Place::Ptr(mplace) = **return_place { - visit.visit(mplace); - } + return_place.visit_tags(visit); // Locals. for local in locals.iter() { if let LocalValue::Live(value) = &local.value { - visit.visit(value); + value.visit_tags(visit); } } - extra.visit_machine_values(visit); + extra.visit_tags(visit); } } @@ -300,8 +295,8 @@ impl<'mir, 'tcx> Default for ThreadManager<'mir, 'tcx> { } } -impl VisitMachineValues for ThreadManager<'_, '_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for ThreadManager<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { let ThreadManager { threads, thread_local_alloc_ids, @@ -312,13 +307,13 @@ impl VisitMachineValues for ThreadManager<'_, '_> { } = self; for thread in threads { - thread.visit_machine_values(visit); + thread.visit_tags(visit); } - for ptr in thread_local_alloc_ids.borrow().values().copied() { - visit.visit(ptr); + for ptr in thread_local_alloc_ids.borrow().values() { + ptr.visit_tags(visit); } for callback in timeout_callbacks.values() { - callback.callback.visit_machine_values(visit); + callback.callback.visit_tags(visit); } } } diff --git a/src/concurrency/weak_memory.rs b/src/concurrency/weak_memory.rs index 15c6c8e9c0e46..9d7a49c0b4301 100644 --- a/src/concurrency/weak_memory.rs +++ b/src/concurrency/weak_memory.rs @@ -108,15 +108,15 @@ pub struct StoreBufferAlloc { store_buffers: RefCell>, } -impl VisitMachineValues for StoreBufferAlloc { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { - for val in self - .store_buffers +impl VisitTags for StoreBufferAlloc { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Self { store_buffers } = self; + for val in store_buffers .borrow() .iter() .flat_map(|buf| buf.buffer.iter().map(|element| &element.val)) { - visit.visit(val); + val.visit_tags(visit); } } } diff --git a/src/intptrcast.rs b/src/intptrcast.rs index b9e5def8fa7cb..9722b7643e426 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -44,6 +44,12 @@ pub struct GlobalStateInner { provenance_mode: ProvenanceMode, } +impl VisitTags for GlobalStateInner { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // Nothing to visit here. + } +} + impl GlobalStateInner { pub fn new(config: &MiriConfig) -> Self { GlobalStateInner { diff --git a/src/lib.rs b/src/lib.rs index 245bdc51a8a75..463feb4dcc8a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,7 @@ pub use crate::range_map::RangeMap; pub use crate::stacked_borrows::{ CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks, }; -pub use crate::tag_gc::{EvalContextExt as _, ProvenanceVisitor, VisitMachineValues}; +pub use crate::tag_gc::{EvalContextExt as _, VisitTags}; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be /// set per default, for maximal validation power. diff --git a/src/machine.rs b/src/machine.rs index 523aad22aa5aa..20ae908fce87c 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -63,13 +63,12 @@ impl<'tcx> std::fmt::Debug for FrameData<'tcx> { } } -impl VisitMachineValues for FrameData<'_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { - let FrameData { catch_unwind, stacked_borrows: _, timing: _ } = self; +impl VisitTags for FrameData<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let FrameData { catch_unwind, stacked_borrows, timing: _ } = self; - if let Some(catch_unwind) = catch_unwind { - catch_unwind.visit_machine_values(visit); - } + catch_unwind.visit_tags(visit); + stacked_borrows.visit_tags(visit); } } @@ -261,17 +260,13 @@ pub struct AllocExtra { pub weak_memory: Option, } -impl VisitMachineValues for AllocExtra { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { - let AllocExtra { stacked_borrows, data_race: _, weak_memory } = self; - - if let Some(stacked_borrows) = stacked_borrows { - stacked_borrows.borrow().visit_machine_values(visit); - } +impl VisitTags for AllocExtra { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let AllocExtra { stacked_borrows, data_race, weak_memory } = self; - if let Some(weak_memory) = weak_memory { - weak_memory.visit_machine_values(visit); - } + stacked_borrows.visit_tags(visit); + data_race.visit_tags(visit); + weak_memory.visit_tags(visit); } } @@ -615,8 +610,9 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { } } -impl VisitMachineValues for MiriMachine<'_, '_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for MiriMachine<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + #[rustfmt::skip] let MiriMachine { threads, tls, @@ -626,25 +622,52 @@ impl VisitMachineValues for MiriMachine<'_, '_> { cmd_line, extern_statics, dir_handler, - .. + stacked_borrows, + data_race, + intptrcast, + file_handler, + tcx: _, + isolated_op: _, + validate: _, + enforce_abi: _, + clock: _, + layouts: _, + static_roots: _, + profiler: _, + string_cache: _, + exported_symbols_cache: _, + panic_on_unsupported: _, + backtrace_style: _, + local_crates: _, + rng: _, + tracked_alloc_ids: _, + check_alignment: _, + cmpxchg_weak_failure_rate: _, + mute_stdout_stderr: _, + weak_memory: _, + preemption_rate: _, + report_progress: _, + basic_block_count: _, + #[cfg(unix)] + external_so_lib: _, + gc_interval: _, + since_gc: _, + num_cpus: _, } = self; - threads.visit_machine_values(visit); - tls.visit_machine_values(visit); - env_vars.visit_machine_values(visit); - dir_handler.visit_machine_values(visit); - - if let Some(argc) = argc { - visit.visit(argc); - } - if let Some(argv) = argv { - visit.visit(argv); - } - if let Some(cmd_line) = cmd_line { - visit.visit(cmd_line); - } - for ptr in extern_statics.values().copied() { - visit.visit(ptr); + threads.visit_tags(visit); + tls.visit_tags(visit); + env_vars.visit_tags(visit); + dir_handler.visit_tags(visit); + file_handler.visit_tags(visit); + data_race.visit_tags(visit); + stacked_borrows.visit_tags(visit); + intptrcast.visit_tags(visit); + argc.visit_tags(visit); + argv.visit_tags(visit); + cmd_line.visit_tags(visit); + for ptr in extern_statics.values() { + ptr.visit_tags(visit); } } } diff --git a/src/shims/env.rs b/src/shims/env.rs index d922014c38352..076d3878de2ac 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -36,15 +36,13 @@ pub struct EnvVars<'tcx> { pub(crate) environ: Option>, } -impl VisitMachineValues for EnvVars<'_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for EnvVars<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { let EnvVars { map, environ } = self; + environ.visit_tags(visit); for ptr in map.values() { - visit.visit(*ptr); - } - if let Some(env) = environ { - visit.visit(**env); + ptr.visit_tags(visit); } } } diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 0d681d3e09b59..698e025961da8 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -35,11 +35,12 @@ pub struct CatchUnwindData<'tcx> { ret: mir::BasicBlock, } -impl VisitMachineValues for CatchUnwindData<'_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { - let CatchUnwindData { catch_fn, data, dest: _, ret: _ } = self; - visit.visit(catch_fn); - visit.visit(data); +impl VisitTags for CatchUnwindData<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let CatchUnwindData { catch_fn, data, dest, ret: _ } = self; + catch_fn.visit_tags(visit); + data.visit_tags(visit); + dest.visit_tags(visit); } } diff --git a/src/shims/time.rs b/src/shims/time.rs index 05eff3dfd59e1..9f04034e1a12d 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -219,7 +219,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(Callback { active_thread }), + Box::new(UnblockCallback { thread_to_unblock: active_thread }), ); Ok(0) @@ -242,24 +242,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.register_timeout_callback( active_thread, Time::Monotonic(timeout_time), - Box::new(Callback { active_thread }), + Box::new(UnblockCallback { thread_to_unblock: active_thread }), ); Ok(()) } } -struct Callback { - active_thread: ThreadId, +struct UnblockCallback { + thread_to_unblock: ThreadId, } -impl VisitMachineValues for Callback { - fn visit_machine_values(&self, _visit: &mut ProvenanceVisitor) {} +impl VisitTags for UnblockCallback { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) {} } -impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback { +impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for UnblockCallback { fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { - ecx.unblock_thread(self.active_thread); + ecx.unblock_thread(self.thread_to_unblock); Ok(()) } } diff --git a/src/shims/tls.rs b/src/shims/tls.rs index 568eb6fa91071..430dedbc1700c 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -235,15 +235,15 @@ impl<'tcx> TlsData<'tcx> { } } -impl VisitMachineValues for TlsData<'_> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for TlsData<'_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { let TlsData { keys, macos_thread_dtors, next_key: _, dtors_running: _ } = self; for scalar in keys.values().flat_map(|v| v.data.values()) { - visit.visit(scalar); + scalar.visit_tags(visit); } for (_, scalar) in macos_thread_dtors.values() { - visit.visit(scalar); + scalar.visit_tags(visit); } } } diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index 5024b2ab45f02..9713cd9265e55 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -256,6 +256,12 @@ pub struct FileHandler { handles: BTreeMap>, } +impl VisitTags for FileHandler { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // All our FileDescriptor do not have any tags. + } +} + impl FileHandler { pub(crate) fn new(mute_stdout_stderr: bool) -> FileHandler { let mut handles: BTreeMap<_, Box> = BTreeMap::new(); @@ -462,12 +468,12 @@ impl Default for DirHandler { } } -impl VisitMachineValues for DirHandler { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for DirHandler { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { let DirHandler { streams, next_id: _ } = self; for dir in streams.values() { - visit.visit(dir.entry); + dir.entry.visit_tags(visit); } } } diff --git a/src/shims/unix/linux/sync.rs b/src/shims/unix/linux/sync.rs index bbfb1c34db7d0..5762ee27b84af 100644 --- a/src/shims/unix/linux/sync.rs +++ b/src/shims/unix/linux/sync.rs @@ -189,6 +189,31 @@ pub fn futex<'tcx>( // Register a timeout callback if a timeout was specified. // This callback will override the return value when the timeout triggers. if let Some(timeout_time) = timeout_time { + struct Callback<'tcx> { + thread: ThreadId, + addr_usize: u64, + dest: PlaceTy<'tcx, Provenance>, + } + + impl<'tcx> VisitTags for Callback<'tcx> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Callback { thread: _, addr_usize: _, dest } = self; + dest.visit_tags(visit); + } + } + + impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + this.unblock_thread(self.thread); + this.futex_remove_waiter(self.addr_usize, self.thread); + let etimedout = this.eval_libc("ETIMEDOUT")?; + this.set_last_error(etimedout)?; + this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; + + Ok(()) + } + } + let dest = dest.clone(); this.register_timeout_callback( thread, @@ -252,30 +277,3 @@ pub fn futex<'tcx>( Ok(()) } - -struct Callback<'tcx> { - thread: ThreadId, - addr_usize: u64, - dest: PlaceTy<'tcx, Provenance>, -} - -impl<'tcx> VisitMachineValues for Callback<'tcx> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { - let Callback { thread: _, addr_usize: _, dest } = self; - if let Place::Ptr(place) = **dest { - visit.visit(place); - } - } -} - -impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { - fn call(&self, this: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { - this.unblock_thread(self.thread); - this.futex_remove_waiter(self.addr_usize, self.thread); - let etimedout = this.eval_libc("ETIMEDOUT")?; - this.set_last_error(etimedout)?; - this.write_scalar(Scalar::from_machine_isize(-1, this), &self.dest)?; - - Ok(()) - } -} diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs index 72b71ada8e0cb..5aafe76ade1d4 100644 --- a/src/shims/unix/sync.rs +++ b/src/shims/unix/sync.rs @@ -851,6 +851,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // We return success for now and override it in the timeout callback. this.write_scalar(Scalar::from_i32(0), dest)?; + struct Callback<'tcx> { + active_thread: ThreadId, + mutex_id: MutexId, + id: CondvarId, + dest: PlaceTy<'tcx, Provenance>, + } + + impl<'tcx> VisitTags for Callback<'tcx> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let Callback { active_thread: _, mutex_id: _, id: _, dest } = self; + dest.visit_tags(visit); + } + } + + impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { + fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { + // We are not waiting for the condvar any more, wait for the + // mutex instead. + reacquire_cond_mutex(ecx, self.active_thread, self.mutex_id)?; + + // Remove the thread from the conditional variable. + ecx.condvar_remove_waiter(self.id, self.active_thread); + + // Set the return value: we timed out. + let etimedout = ecx.eval_libc("ETIMEDOUT")?; + ecx.write_scalar(etimedout, &self.dest)?; + + Ok(()) + } + } + // Register the timeout callback. let dest = dest.clone(); this.register_timeout_callback( @@ -885,39 +916,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } -struct Callback<'tcx> { - active_thread: ThreadId, - mutex_id: MutexId, - id: CondvarId, - dest: PlaceTy<'tcx, Provenance>, -} - -impl<'tcx> VisitMachineValues for Callback<'tcx> { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { - let Callback { active_thread: _, mutex_id: _, id: _, dest } = self; - if let Place::Ptr(place) = **dest { - visit.visit(place); - } - } -} - -impl<'mir, 'tcx: 'mir> MachineCallback<'mir, 'tcx> for Callback<'tcx> { - fn call(&self, ecx: &mut MiriInterpCx<'mir, 'tcx>) -> InterpResult<'tcx> { - // We are not waiting for the condvar any more, wait for the - // mutex instead. - reacquire_cond_mutex(ecx, self.active_thread, self.mutex_id)?; - - // Remove the thread from the conditional variable. - ecx.condvar_remove_waiter(self.id, self.active_thread); - - // Set the return value: we timed out. - let etimedout = ecx.eval_libc("ETIMEDOUT")?; - ecx.write_scalar(etimedout, &self.dest)?; - - Ok(()) - } -} - fn layout_of_maybe_uninit<'tcx>(tcx: TyCtxtAt<'tcx>, param: Ty<'tcx>) -> TyAndLayout<'tcx> { let def_id = tcx.require_lang_item(LangItem::MaybeUninit, None); let ty = tcx.bound_type_of(def_id).subst(*tcx, &[param.into()]); diff --git a/src/stacked_borrows/mod.rs b/src/stacked_borrows/mod.rs index b40358e2c15a3..829703d656262 100644 --- a/src/stacked_borrows/mod.rs +++ b/src/stacked_borrows/mod.rs @@ -71,6 +71,12 @@ pub struct FrameExtra { protected_tags: SmallVec<[SbTag; 2]>, } +impl VisitTags for FrameExtra { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // `protected_tags` are fine to GC. + } +} + /// Extra per-allocation state. #[derive(Clone, Debug)] pub struct Stacks { @@ -109,6 +115,13 @@ pub struct GlobalStateInner { retag_fields: bool, } +impl VisitTags for GlobalStateInner { + fn visit_tags(&self, _visit: &mut dyn FnMut(SbTag)) { + // The only candidate is base_ptr_tags, and that does not need visiting since we don't ever + // GC the bottommost tag. + } +} + /// We need interior mutable access to the global state. pub type GlobalState = RefCell; @@ -513,10 +526,10 @@ impl Stacks { } } -impl VisitMachineValues for Stacks { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for Stacks { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { for tag in self.exposed_tags.iter().copied() { - visit.visit(tag); + visit(tag); } } } diff --git a/src/tag_gc.rs b/src/tag_gc.rs index e2273f055dd9b..5aa653632f395 100644 --- a/src/tag_gc.rs +++ b/src/tag_gc.rs @@ -2,123 +2,155 @@ use rustc_data_structures::fx::FxHashSet; use crate::*; -pub trait VisitMachineValues { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor); +pub trait VisitTags { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)); } -pub trait MachineValue { - fn visit_provenance(&self, tags: &mut FxHashSet); +impl VisitTags for Option { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + if let Some(x) = self { + x.visit_tags(visit); + } + } } -pub struct ProvenanceVisitor { - tags: FxHashSet, +impl VisitTags for std::cell::RefCell { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + self.borrow().visit_tags(visit) + } } -impl ProvenanceVisitor { - pub fn visit(&mut self, v: V) - where - V: MachineValue, - { - v.visit_provenance(&mut self.tags); +impl VisitTags for SbTag { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + visit(*self) } } -impl MachineValue for &T { - fn visit_provenance(&self, tags: &mut FxHashSet) { - (**self).visit_provenance(tags); +impl VisitTags for Provenance { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + if let Provenance::Concrete { sb, .. } = self { + visit(*sb); + } } } -impl MachineValue for Operand { - fn visit_provenance(&self, tags: &mut FxHashSet) { +impl VisitTags for Pointer { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let (prov, _offset) = self.into_parts(); + prov.visit_tags(visit); + } +} + +impl VisitTags for Pointer> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let (prov, _offset) = self.into_parts(); + prov.visit_tags(visit); + } +} + +impl VisitTags for Scalar { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { match self { - Operand::Immediate(Immediate::Scalar(s)) => { - s.visit_provenance(tags); - } - Operand::Immediate(Immediate::ScalarPair(s1, s2)) => { - s1.visit_provenance(tags); - s2.visit_provenance(tags); - } - Operand::Immediate(Immediate::Uninit) => {} - Operand::Indirect(p) => { - p.visit_provenance(tags); - } + Scalar::Ptr(ptr, _) => ptr.visit_tags(visit), + Scalar::Int(_) => (), } } } -impl MachineValue for Scalar { - fn visit_provenance(&self, tags: &mut FxHashSet) { - if let Scalar::Ptr(ptr, _) = self { - if let Provenance::Concrete { sb, .. } = ptr.provenance { - tags.insert(sb); +impl VisitTags for Immediate { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Immediate::Scalar(s) => { + s.visit_tags(visit); + } + Immediate::ScalarPair(s1, s2) => { + s1.visit_tags(visit); + s2.visit_tags(visit); } + Immediate::Uninit => {} } } } -impl MachineValue for MemPlace { - fn visit_provenance(&self, tags: &mut FxHashSet) { - if let Some(Provenance::Concrete { sb, .. }) = self.ptr.provenance { - tags.insert(sb); +impl VisitTags for MemPlaceMeta { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + MemPlaceMeta::Meta(m) => m.visit_tags(visit), + MemPlaceMeta::None => {} } } } -impl MachineValue for SbTag { - fn visit_provenance(&self, tags: &mut FxHashSet) { - tags.insert(*self); +impl VisitTags for MemPlace { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + let MemPlace { ptr, meta } = self; + ptr.visit_tags(visit); + meta.visit_tags(visit); } } -impl MachineValue for Pointer { - fn visit_provenance(&self, tags: &mut FxHashSet) { - let (prov, _offset) = self.into_parts(); - if let Provenance::Concrete { sb, .. } = prov { - tags.insert(sb); +impl VisitTags for MPlaceTy<'_, Provenance> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + (**self).visit_tags(visit) + } +} + +impl VisitTags for Place { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Place::Ptr(p) => p.visit_tags(visit), + Place::Local { .. } => { + // Will be visited as part of the stack frame. + } } } } -impl MachineValue for Pointer> { - fn visit_provenance(&self, tags: &mut FxHashSet) { - let (prov, _offset) = self.into_parts(); - if let Some(Provenance::Concrete { sb, .. }) = prov { - tags.insert(sb); +impl VisitTags for PlaceTy<'_, Provenance> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + (**self).visit_tags(visit) + } +} + +impl VisitTags for Operand { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { + match self { + Operand::Immediate(imm) => { + imm.visit_tags(visit); + } + Operand::Indirect(p) => { + p.visit_tags(visit); + } } } } -impl VisitMachineValues for Allocation { - fn visit_machine_values(&self, visit: &mut ProvenanceVisitor) { +impl VisitTags for Allocation { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { for (_size, prov) in self.provenance().iter() { - if let Provenance::Concrete { sb, .. } = prov { - visit.visit(*sb); - } + prov.visit_tags(visit); } - self.extra.visit_machine_values(visit); + self.extra.visit_tags(visit); } } -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} -pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { - /// GC helper to visit everything that can store provenance. The `ProvenanceVisitor` knows how - /// to extract provenance from the interpreter data types. - fn visit_all_machine_values(&self, acc: &mut ProvenanceVisitor) { - let this = self.eval_context_ref(); - +impl VisitTags for crate::MiriInterpCx<'_, '_> { + fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) { // Memory. - this.memory.alloc_map().iter(|it| { + self.memory.alloc_map().iter(|it| { for (_id, (_kind, alloc)) in it { - alloc.visit_machine_values(acc); + alloc.visit_tags(visit); } }); // And all the other machine values. - this.machine.visit_machine_values(acc); + self.machine.visit_tags(visit); } +} +impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} +pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn garbage_collect_tags(&mut self) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // No reason to do anything at all if stacked borrows is off. @@ -126,9 +158,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { return Ok(()); } - let mut visitor = ProvenanceVisitor { tags: FxHashSet::default() }; - this.visit_all_machine_values(&mut visitor); - self.remove_unreachable_tags(visitor.tags); + let mut tags = FxHashSet::default(); + this.visit_tags(&mut |tag| { + tags.insert(tag); + }); + self.remove_unreachable_tags(tags); Ok(()) }