Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update Miri #104989

Merged
merged 40 commits into from
Nov 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7225524
add a weak form of protection that justifies Box noalias
RalfJung Nov 20, 2022
bf9e73f
some things don't need to be mutable
RalfJung Nov 20, 2022
32e9d00
tweaks
RalfJung Nov 20, 2022
105dba7
Auto merge of #2684 - RalfJung:stack-borrows-weak-protectors, r=saethlin
bors Nov 21, 2022
23270ae
Incrementally track which frame to use for diagnostics
saethlin Nov 3, 2022
859310a
ensure current getrandom works with strict provenance
RalfJung Nov 22, 2022
8061e2f
update test_dependencies
RalfJung Nov 22, 2022
8b0b2d1
Auto merge of #2687 - RalfJung:getrandom, r=RalfJung
bors Nov 22, 2022
1ca3c29
Document is_user_relevant
saethlin Nov 22, 2022
a312329
Update src/machine.rs
saethlin Nov 23, 2022
448f044
replace a borrow_mut by get_mut
RalfJung Nov 25, 2022
fe81522
Auto merge of #2691 - RalfJung:get_mut, r=RalfJung
bors Nov 25, 2022
2c456b5
Test a small cargo-miri smoke test even in `run_tests_minimal`
Noratrieb Nov 24, 2022
8961e13
Use None when the stack is empty
saethlin Nov 25, 2022
726b9d0
caller_span only makes sense when there are 2 frames on the stack
RalfJung Nov 26, 2022
7d0db1e
Auto merge of #2647 - saethlin:current-span, r=RalfJung
bors Nov 26, 2022
166e60e
update lockfile
RalfJung Nov 26, 2022
4d3e565
Auto merge of #2690 - Nilstrieb:cargo-miri-smoke-test-ci-so-that-carg…
bors Nov 26, 2022
56a1d07
prettify our CI logs
RalfJung Nov 26, 2022
b3e4402
Auto merge of #2695 - RalfJung:ci-pretty, r=RalfJung
bors Nov 26, 2022
0822c31
add namespace to resolve_path
beepster4096 Nov 9, 2022
245857b
refactor try_resolve_did and also support resolving crates/modules
RalfJung Nov 26, 2022
3158a8d
support no_std on Windows
RalfJung Nov 26, 2022
144b485
Auto merge of #2696 - RalfJung:no-std-windows, r=RalfJung
bors Nov 26, 2022
f479404
!Unpin retags must still be reads, to check dereferenceable
RalfJung Nov 26, 2022
a7f7221
slightly adjust and synchronize Machine passing for SB and DataRace
RalfJung Nov 26, 2022
a3bd578
make Stacked Borrows retags act like data races
RalfJung Nov 26, 2022
edf8154
nits
RalfJung Nov 26, 2022
958d591
Use `.wasm` extension when building for wasm in cargo-miri
Noratrieb Nov 21, 2022
b20efbd
CI: fix begingroup printing
RalfJung Nov 27, 2022
5a14c5a
Auto merge of #2700 - RalfJung:begingroup, r=RalfJung
bors Nov 27, 2022
c6587b0
run_tests_minimal: actually run the smoke test on the desired target
RalfJung Nov 27, 2022
9f8df93
Auto merge of #2701 - RalfJung:smoke, r=RalfJung
bors Nov 27, 2022
a83b105
Auto merge of #2685 - Nilstrieb:cargo-miri-wasm, r=RalfJung
bors Nov 27, 2022
66354f0
Auto merge of #2694 - RalfJung:retag-deref-check, r=saethlin
bors Nov 27, 2022
187ba67
Preparing for merge from rustc
RalfJung Nov 27, 2022
7c12ed1
Merge from rustc
RalfJung Nov 27, 2022
6d1e99e
advice on josh pushing
RalfJung Nov 27, 2022
598c3da
clippy
RalfJung Nov 27, 2022
f8fbc6d
Auto merge of #2702 - RalfJung:rustup, r=RalfJung
bors Nov 27, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/tools/miri/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,13 @@ needed.

### Exporting changes to the rustc repo

Keep in mind that pushing is the most complicated job that josh has to do --
pulling just filters the rustc history, but pushing needs to construct a new
rustc history that would filter to the given Miri history! To avoid problems, it
is a good idea to always pull immediately before you push. In particular, you
should never do two josh pushes without an intermediate pull; that can lead to
duplicated commits.

Josh needs to be running, as described above. We will use the josh proxy to push
to your fork of rustc. Run the following in the Miri repo, assuming we are on an
up-to-date master branch:
Expand Down
3 changes: 2 additions & 1 deletion src/tools/miri/cargo-miri/src/phases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,9 +281,10 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
}
info.store(&filename);
// For Windows, do the same thing again with `.exe` appended to the filename.
// For Windows and WASM, do the same thing again with `.exe`/`.wasm` appended to the filename.
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
info.store(&out_filename("", ".exe"));
info.store(&out_filename("", ".wasm"));
};

let runnable_crate = !info_query && is_runnable_crate();
Expand Down
33 changes: 26 additions & 7 deletions src/tools/miri/ci.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
#!/bin/bash
set -euo pipefail
set -x

function begingroup {
echo "::group::$@"
set -x
}

function endgroup {
set +x
echo "::endgroup"
}

begingroup "Building Miri"

# Determine configuration for installed build
echo "Installing release version of Miri"
Expand All @@ -14,14 +25,15 @@ export CARGO_EXTRA_FLAGS="--locked"
./miri check --no-default-features # make sure this can be built
./miri check --all-features # and this, too
./miri build --all-targets # the build that all the `./miri test` below will use
echo

endgroup

# Test
function run_tests {
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
echo "Testing foreign architecture $MIRI_TEST_TARGET"
begingroup "Testing foreign architecture $MIRI_TEST_TARGET"
else
echo "Testing host architecture"
begingroup "Testing host architecture"
fi

## ui test suite
Expand Down Expand Up @@ -52,7 +64,6 @@ function run_tests {
echo 'build.rustc-wrapper = "thisdoesnotexist"' > .cargo/config.toml
# Run the actual test
${PYTHON} test-cargo-miri/run-test.py
echo
# Clean up
unset RUSTC MIRI
rm -rf .cargo
Expand All @@ -63,16 +74,23 @@ function run_tests {
cargo miri run --manifest-path bench-cargo-miri/$BENCH/Cargo.toml
done
fi

endgroup
}

function run_tests_minimal {
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
echo "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
else
echo "Testing MINIMAL host architecture: only testing $@"
begingroup "Testing MINIMAL host architecture: only testing $@"
fi

./miri test -- "$@"

# Ensure that a small smoke test of cargo-miri works.
cargo miri run --manifest-path test-cargo-miri/no-std-smoke/Cargo.toml --target ${MIRI_TEST_TARGET-$HOST_TARGET}

endgroup
}

# host
Expand All @@ -85,6 +103,7 @@ case $HOST_TARGET in
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
MIRI_TEST_TARGET=wasm32-wasi MIRI_NO_STD=1 run_tests_minimal no_std # supports std but miri doesn't support it
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
;;
x86_64-apple-darwin)
Expand Down
2 changes: 1 addition & 1 deletion src/tools/miri/rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7477c1f4f7d6bef037d523099b240d22aa1b63a0
454784afba5bf35b5ff14ada0e31265ad1d75e73
26 changes: 12 additions & 14 deletions src/tools/miri/src/concurrency/data_race.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,18 +838,18 @@ impl VClockAlloc {
&self,
alloc_id: AllocId,
range: AllocRange,
global: &GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let global = machine.data_race.as_ref().unwrap();
if global.race_detecting() {
let (index, clocks) = global.current_thread_state(thread_mgr);
let (index, clocks) = global.current_thread_state(&machine.threads);
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
if let Err(DataRace) = range.read_race_detect(&clocks, index) {
// Report data-race.
return Self::report_data_race(
global,
thread_mgr,
&machine.threads,
range,
"Read",
false,
Expand All @@ -869,17 +869,17 @@ impl VClockAlloc {
alloc_id: AllocId,
range: AllocRange,
write_type: WriteType,
global: &mut GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
let global = machine.data_race.as_mut().unwrap();
if global.race_detecting() {
let (index, clocks) = global.current_thread_state(thread_mgr);
let (index, clocks) = global.current_thread_state(&machine.threads);
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
// Report data-race
return Self::report_data_race(
global,
thread_mgr,
&machine.threads,
range,
write_type.get_descriptor(),
false,
Expand All @@ -901,10 +901,9 @@ impl VClockAlloc {
&mut self,
alloc_id: AllocId,
range: AllocRange,
global: &mut GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
self.unique_access(alloc_id, range, WriteType::Write, global, thread_mgr)
self.unique_access(alloc_id, range, WriteType::Write, machine)
}

/// Detect data-races for an unsynchronized deallocate operation, will not perform
Expand All @@ -915,10 +914,9 @@ impl VClockAlloc {
&mut self,
alloc_id: AllocId,
range: AllocRange,
global: &mut GlobalState,
thread_mgr: &ThreadManager<'_, '_>,
machine: &mut MiriMachine<'_, '_>,
) -> InterpResult<'tcx> {
self.unique_access(alloc_id, range, WriteType::Deallocate, global, thread_mgr)
self.unique_access(alloc_id, range, WriteType::Deallocate, machine)
}
}

Expand Down
55 changes: 52 additions & 3 deletions src/tools/miri/src/concurrency/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ pub struct Thread<'mir, 'tcx> {
/// The virtual call stack.
stack: Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>>,

/// The index of the topmost user-relevant frame in `stack`. This field must contain
/// the value produced by `get_top_user_relevant_frame`.
/// The `None` state here represents
/// This field is a cache to reduce how often we call that method. The cache is manually
/// maintained inside `MiriMachine::after_stack_push` and `MiriMachine::after_stack_pop`.
top_user_relevant_frame: Option<usize>,

/// The join status.
join_status: ThreadJoinStatus,

Expand Down Expand Up @@ -147,6 +154,40 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
fn thread_name(&self) -> &[u8] {
if let Some(ref thread_name) = self.thread_name { thread_name } else { b"<unnamed>" }
}

/// Return the top user-relevant frame, if there is one.
/// Note that the choice to return `None` here when there is no user-relevant frame is part of
/// justifying the optimization that only pushes of user-relevant frames require updating the
/// `top_user_relevant_frame` field.
fn compute_top_user_relevant_frame(&self) -> Option<usize> {
self.stack
.iter()
.enumerate()
.rev()
.find_map(|(idx, frame)| if frame.extra.is_user_relevant { Some(idx) } else { None })
}

/// Re-compute the top user-relevant frame from scratch.
pub fn recompute_top_user_relevant_frame(&mut self) {
self.top_user_relevant_frame = self.compute_top_user_relevant_frame();
}

/// Set the top user-relevant frame to the given value. Must be equal to what
/// `get_top_user_relevant_frame` would return!
pub fn set_top_user_relevant_frame(&mut self, frame_idx: usize) {
debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame());
self.top_user_relevant_frame = Some(frame_idx);
}

/// Returns the topmost frame that is considered user-relevant, or the
/// top of the stack if there is no such frame, or `None` if the stack is empty.
pub fn top_user_relevant_frame(&self) -> Option<usize> {
debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame());
// This can be called upon creation of an allocation. We create allocations while setting up
// parts of the Rust runtime when we do not have any stack frames yet, so we need to handle
// empty stacks.
self.top_user_relevant_frame.or_else(|| self.stack.len().checked_sub(1))
}
}

impl<'mir, 'tcx> std::fmt::Debug for Thread<'mir, 'tcx> {
Expand All @@ -167,6 +208,7 @@ impl<'mir, 'tcx> Default for Thread<'mir, 'tcx> {
state: ThreadState::Enabled,
thread_name: None,
stack: Vec::new(),
top_user_relevant_frame: None,
join_status: ThreadJoinStatus::Joinable,
panic_payload: None,
last_error: None,
Expand All @@ -184,8 +226,15 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {

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;
let Thread {
panic_payload,
last_error,
stack,
top_user_relevant_frame: _,
state: _,
thread_name: _,
join_status: _,
} = self;

panic_payload.visit_tags(visit);
last_error.visit_tags(visit);
Expand Down Expand Up @@ -414,7 +463,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
}

/// Get a shared borrow of the currently active thread.
fn active_thread_ref(&self) -> &Thread<'mir, 'tcx> {
pub fn active_thread_ref(&self) -> &Thread<'mir, 'tcx> {
&self.threads[self.active_thread]
}

Expand Down
3 changes: 2 additions & 1 deletion src/tools/miri/src/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::thread;
use log::info;

use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{
self,
Expand Down Expand Up @@ -195,7 +196,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
MiriMachine::late_init(&mut ecx, config)?;

// Make sure we have MIR. We check MIR for some stable monomorphic function in libcore.
let sentinel = ecx.try_resolve_path(&["core", "ascii", "escape_default"]);
let sentinel = ecx.try_resolve_path(&["core", "ascii", "escape_default"], Namespace::ValueNS);
if !matches!(sentinel, Some(s) if tcx.is_mir_available(s.def.def_id())) {
tcx.sess.fatal(
"the current sysroot was built without `-Zalways-encode-mir`, or libcore seems missing. \
Expand Down
Loading