Skip to content

Commit 2ccb38b

Browse files
authored
Rollup merge of #104989 - RalfJung:miri, r=RalfJung
update Miri r? `@ghost`
2 parents 5ea36cf + f8fbc6d commit 2ccb38b

File tree

81 files changed

+893
-500
lines changed

Some content is hidden

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

81 files changed

+893
-500
lines changed

src/tools/miri/CONTRIBUTING.md

+7
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,13 @@ needed.
296296

297297
### Exporting changes to the rustc repo
298298

299+
Keep in mind that pushing is the most complicated job that josh has to do --
300+
pulling just filters the rustc history, but pushing needs to construct a new
301+
rustc history that would filter to the given Miri history! To avoid problems, it
302+
is a good idea to always pull immediately before you push. In particular, you
303+
should never do two josh pushes without an intermediate pull; that can lead to
304+
duplicated commits.
305+
299306
Josh needs to be running, as described above. We will use the josh proxy to push
300307
to your fork of rustc. Run the following in the Miri repo, assuming we are on an
301308
up-to-date master branch:

src/tools/miri/cargo-miri/src/phases.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,10 @@ pub fn phase_rustc(mut args: impl Iterator<Item = String>, phase: RustcPhase) {
281281
eprintln!("[cargo-miri rustc] writing run info to `{}`", filename.display());
282282
}
283283
info.store(&filename);
284-
// For Windows, do the same thing again with `.exe` appended to the filename.
284+
// For Windows and WASM, do the same thing again with `.exe`/`.wasm` appended to the filename.
285285
// (Need to do this here as cargo moves that "binary" to a different place before running it.)
286286
info.store(&out_filename("", ".exe"));
287+
info.store(&out_filename("", ".wasm"));
287288
};
288289

289290
let runnable_crate = !info_query && is_runnable_crate();

src/tools/miri/ci.sh

+26-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
#!/bin/bash
22
set -euo pipefail
3-
set -x
3+
4+
function begingroup {
5+
echo "::group::$@"
6+
set -x
7+
}
8+
9+
function endgroup {
10+
set +x
11+
echo "::endgroup"
12+
}
13+
14+
begingroup "Building Miri"
415

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

1931
# Test
2032
function run_tests {
2133
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
22-
echo "Testing foreign architecture $MIRI_TEST_TARGET"
34+
begingroup "Testing foreign architecture $MIRI_TEST_TARGET"
2335
else
24-
echo "Testing host architecture"
36+
begingroup "Testing host architecture"
2537
fi
2638

2739
## ui test suite
@@ -52,7 +64,6 @@ function run_tests {
5264
echo 'build.rustc-wrapper = "thisdoesnotexist"' > .cargo/config.toml
5365
# Run the actual test
5466
${PYTHON} test-cargo-miri/run-test.py
55-
echo
5667
# Clean up
5768
unset RUSTC MIRI
5869
rm -rf .cargo
@@ -63,16 +74,23 @@ function run_tests {
6374
cargo miri run --manifest-path bench-cargo-miri/$BENCH/Cargo.toml
6475
done
6576
fi
77+
78+
endgroup
6679
}
6780

6881
function run_tests_minimal {
6982
if [ -n "${MIRI_TEST_TARGET+exists}" ]; then
70-
echo "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
83+
begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@"
7184
else
72-
echo "Testing MINIMAL host architecture: only testing $@"
85+
begingroup "Testing MINIMAL host architecture: only testing $@"
7386
fi
7487

7588
./miri test -- "$@"
89+
90+
# Ensure that a small smoke test of cargo-miri works.
91+
cargo miri run --manifest-path test-cargo-miri/no-std-smoke/Cargo.toml --target ${MIRI_TEST_TARGET-$HOST_TARGET}
92+
93+
endgroup
7694
}
7795

7896
# host
@@ -85,6 +103,7 @@ case $HOST_TARGET in
85103
MIRI_TEST_TARGET=i686-pc-windows-msvc run_tests
86104
MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple atomic data_race env/var
87105
MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic
106+
MIRI_TEST_TARGET=wasm32-wasi MIRI_NO_STD=1 run_tests_minimal no_std # supports std but miri doesn't support it
88107
MIRI_TEST_TARGET=thumbv7em-none-eabihf MIRI_NO_STD=1 run_tests_minimal no_std # no_std embedded architecture
89108
;;
90109
x86_64-apple-darwin)

src/tools/miri/rust-version

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
7477c1f4f7d6bef037d523099b240d22aa1b63a0
1+
454784afba5bf35b5ff14ada0e31265ad1d75e73

src/tools/miri/src/concurrency/data_race.rs

+12-14
Original file line numberDiff line numberDiff line change
@@ -838,18 +838,18 @@ impl VClockAlloc {
838838
&self,
839839
alloc_id: AllocId,
840840
range: AllocRange,
841-
global: &GlobalState,
842-
thread_mgr: &ThreadManager<'_, '_>,
841+
machine: &MiriMachine<'_, '_>,
843842
) -> InterpResult<'tcx> {
843+
let global = machine.data_race.as_ref().unwrap();
844844
if global.race_detecting() {
845-
let (index, clocks) = global.current_thread_state(thread_mgr);
845+
let (index, clocks) = global.current_thread_state(&machine.threads);
846846
let mut alloc_ranges = self.alloc_ranges.borrow_mut();
847847
for (offset, range) in alloc_ranges.iter_mut(range.start, range.size) {
848848
if let Err(DataRace) = range.read_race_detect(&clocks, index) {
849849
// Report data-race.
850850
return Self::report_data_race(
851851
global,
852-
thread_mgr,
852+
&machine.threads,
853853
range,
854854
"Read",
855855
false,
@@ -869,17 +869,17 @@ impl VClockAlloc {
869869
alloc_id: AllocId,
870870
range: AllocRange,
871871
write_type: WriteType,
872-
global: &mut GlobalState,
873-
thread_mgr: &ThreadManager<'_, '_>,
872+
machine: &mut MiriMachine<'_, '_>,
874873
) -> InterpResult<'tcx> {
874+
let global = machine.data_race.as_mut().unwrap();
875875
if global.race_detecting() {
876-
let (index, clocks) = global.current_thread_state(thread_mgr);
876+
let (index, clocks) = global.current_thread_state(&machine.threads);
877877
for (offset, range) in self.alloc_ranges.get_mut().iter_mut(range.start, range.size) {
878878
if let Err(DataRace) = range.write_race_detect(&clocks, index, write_type) {
879879
// Report data-race
880880
return Self::report_data_race(
881881
global,
882-
thread_mgr,
882+
&machine.threads,
883883
range,
884884
write_type.get_descriptor(),
885885
false,
@@ -901,10 +901,9 @@ impl VClockAlloc {
901901
&mut self,
902902
alloc_id: AllocId,
903903
range: AllocRange,
904-
global: &mut GlobalState,
905-
thread_mgr: &ThreadManager<'_, '_>,
904+
machine: &mut MiriMachine<'_, '_>,
906905
) -> InterpResult<'tcx> {
907-
self.unique_access(alloc_id, range, WriteType::Write, global, thread_mgr)
906+
self.unique_access(alloc_id, range, WriteType::Write, machine)
908907
}
909908

910909
/// Detect data-races for an unsynchronized deallocate operation, will not perform
@@ -915,10 +914,9 @@ impl VClockAlloc {
915914
&mut self,
916915
alloc_id: AllocId,
917916
range: AllocRange,
918-
global: &mut GlobalState,
919-
thread_mgr: &ThreadManager<'_, '_>,
917+
machine: &mut MiriMachine<'_, '_>,
920918
) -> InterpResult<'tcx> {
921-
self.unique_access(alloc_id, range, WriteType::Deallocate, global, thread_mgr)
919+
self.unique_access(alloc_id, range, WriteType::Deallocate, machine)
922920
}
923921
}
924922

src/tools/miri/src/concurrency/thread.rs

+52-3
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,13 @@ pub struct Thread<'mir, 'tcx> {
118118
/// The virtual call stack.
119119
stack: Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>>,
120120

121+
/// The index of the topmost user-relevant frame in `stack`. This field must contain
122+
/// the value produced by `get_top_user_relevant_frame`.
123+
/// The `None` state here represents
124+
/// This field is a cache to reduce how often we call that method. The cache is manually
125+
/// maintained inside `MiriMachine::after_stack_push` and `MiriMachine::after_stack_pop`.
126+
top_user_relevant_frame: Option<usize>,
127+
121128
/// The join status.
122129
join_status: ThreadJoinStatus,
123130

@@ -147,6 +154,40 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
147154
fn thread_name(&self) -> &[u8] {
148155
if let Some(ref thread_name) = self.thread_name { thread_name } else { b"<unnamed>" }
149156
}
157+
158+
/// Return the top user-relevant frame, if there is one.
159+
/// Note that the choice to return `None` here when there is no user-relevant frame is part of
160+
/// justifying the optimization that only pushes of user-relevant frames require updating the
161+
/// `top_user_relevant_frame` field.
162+
fn compute_top_user_relevant_frame(&self) -> Option<usize> {
163+
self.stack
164+
.iter()
165+
.enumerate()
166+
.rev()
167+
.find_map(|(idx, frame)| if frame.extra.is_user_relevant { Some(idx) } else { None })
168+
}
169+
170+
/// Re-compute the top user-relevant frame from scratch.
171+
pub fn recompute_top_user_relevant_frame(&mut self) {
172+
self.top_user_relevant_frame = self.compute_top_user_relevant_frame();
173+
}
174+
175+
/// Set the top user-relevant frame to the given value. Must be equal to what
176+
/// `get_top_user_relevant_frame` would return!
177+
pub fn set_top_user_relevant_frame(&mut self, frame_idx: usize) {
178+
debug_assert_eq!(Some(frame_idx), self.compute_top_user_relevant_frame());
179+
self.top_user_relevant_frame = Some(frame_idx);
180+
}
181+
182+
/// Returns the topmost frame that is considered user-relevant, or the
183+
/// top of the stack if there is no such frame, or `None` if the stack is empty.
184+
pub fn top_user_relevant_frame(&self) -> Option<usize> {
185+
debug_assert_eq!(self.top_user_relevant_frame, self.compute_top_user_relevant_frame());
186+
// This can be called upon creation of an allocation. We create allocations while setting up
187+
// parts of the Rust runtime when we do not have any stack frames yet, so we need to handle
188+
// empty stacks.
189+
self.top_user_relevant_frame.or_else(|| self.stack.len().checked_sub(1))
190+
}
150191
}
151192

152193
impl<'mir, 'tcx> std::fmt::Debug for Thread<'mir, 'tcx> {
@@ -167,6 +208,7 @@ impl<'mir, 'tcx> Default for Thread<'mir, 'tcx> {
167208
state: ThreadState::Enabled,
168209
thread_name: None,
169210
stack: Vec::new(),
211+
top_user_relevant_frame: None,
170212
join_status: ThreadJoinStatus::Joinable,
171213
panic_payload: None,
172214
last_error: None,
@@ -184,8 +226,15 @@ impl<'mir, 'tcx> Thread<'mir, 'tcx> {
184226

185227
impl VisitTags for Thread<'_, '_> {
186228
fn visit_tags(&self, visit: &mut dyn FnMut(SbTag)) {
187-
let Thread { panic_payload, last_error, stack, state: _, thread_name: _, join_status: _ } =
188-
self;
229+
let Thread {
230+
panic_payload,
231+
last_error,
232+
stack,
233+
top_user_relevant_frame: _,
234+
state: _,
235+
thread_name: _,
236+
join_status: _,
237+
} = self;
189238

190239
panic_payload.visit_tags(visit);
191240
last_error.visit_tags(visit);
@@ -414,7 +463,7 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
414463
}
415464

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

src/tools/miri/src/eval.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::thread;
99
use log::info;
1010

1111
use rustc_data_structures::fx::FxHashSet;
12+
use rustc_hir::def::Namespace;
1213
use rustc_hir::def_id::DefId;
1314
use rustc_middle::ty::{
1415
self,
@@ -195,7 +196,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
195196
MiriMachine::late_init(&mut ecx, config)?;
196197

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

0 commit comments

Comments
 (0)