Skip to content

Commit 3c3ae2c

Browse files
committed
Auto merge of #111867 - RalfJung:miri, r=RalfJung
update Miri
2 parents 80380ca + a238793 commit 3c3ae2c

File tree

19 files changed

+148
-49
lines changed

19 files changed

+148
-49
lines changed

Cargo.lock

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ smallvec = "1.7"
2929
# for more information.
3030
rustc-workspace-hack = "1.0.0"
3131
measureme = "10.0.0"
32+
ctrlc = "3.2.5"
3233

3334
[target.'cfg(unix)'.dependencies]
3435
libc = "0.2"

cargo-miri/src/arg.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ impl<'s, I: Iterator<Item = Cow<'s, str>>> Iterator for ArgSplitFlagValue<'_, I>
4040
if arg == "--" {
4141
// Stop searching at `--`.
4242
self.args = None;
43-
return None;
43+
// But yield the `--` so that it does not get lost!
44+
return Some(Err(Cow::Borrowed("--")));
4445
}
4546
// These branches cannot be merged if we want to avoid the allocation in the `Borrowed` branch.
4647
match &arg {
@@ -79,9 +80,8 @@ impl<'a, I: Iterator<Item = String> + 'a> ArgSplitFlagValue<'a, I> {
7980
) -> impl Iterator<Item = Result<String, String>> + 'a {
8081
ArgSplitFlagValue::new(args.map(Cow::Owned), name).map(|x| {
8182
match x {
82-
Ok(Cow::Owned(s)) => Ok(s),
83-
Err(Cow::Owned(s)) => Err(s),
84-
_ => panic!("iterator converted owned to borrowed"),
83+
Ok(s) => Ok(s.into_owned()),
84+
Err(s) => Err(s.into_owned()),
8585
}
8686
})
8787
}

cargo-miri/src/phases.rs

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -113,30 +113,17 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
113113
};
114114
let metadata = get_cargo_metadata();
115115
let mut cmd = cargo();
116-
cmd.arg(cargo_cmd);
117-
118-
// Forward all arguments before `--` other than `--target-dir` and its value to Cargo.
119-
// (We want to *change* the target-dir value, so we must not forward it.)
120-
let mut target_dir = None;
121-
for arg in ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir") {
122-
match arg {
123-
Ok(value) => {
124-
if target_dir.is_some() {
125-
show_error!("`--target-dir` is provided more than once");
126-
}
127-
target_dir = Some(value.into());
128-
}
129-
Err(arg) => {
130-
cmd.arg(arg);
131-
}
132-
}
116+
cmd.arg(&cargo_cmd);
117+
// In nextest we have to also forward the main `verb`.
118+
if cargo_cmd == "nextest" {
119+
cmd.arg(
120+
args.next()
121+
.unwrap_or_else(|| show_error!("`cargo miri nextest` expects a verb (e.g. `run`)")),
122+
);
133123
}
134-
// Detect the target directory if it's not specified via `--target-dir`.
135-
// (`cargo metadata` does not support `--target-dir`, that's why we have to handle this ourselves.)
136-
let target_dir = target_dir.get_or_insert_with(|| metadata.target_directory.clone());
137-
// Set `--target-dir` to `miri` inside the original target directory.
138-
target_dir.push("miri");
139-
cmd.arg("--target-dir").arg(target_dir);
124+
// We set the following flags *before* forwarding more arguments.
125+
// This is needed to fix <https://github.com/rust-lang/miri/issues/2829>: cargo will stop
126+
// interpreting things as flags when it sees the first positional argument.
140127

141128
// Make sure the build target is explicitly set.
142129
// This is needed to make the `target.runner` settings do something,
@@ -154,8 +141,23 @@ pub fn phase_cargo_miri(mut args: impl Iterator<Item = String>) {
154141
cmd.arg("--config")
155142
.arg(format!("target.'cfg(all())'.runner=[{cargo_miri_path_for_toml}, 'runner']"));
156143

157-
// Forward all further arguments after `--` to cargo.
158-
cmd.arg("--").args(args);
144+
// Set `--target-dir` to `miri` inside the original target directory.
145+
let mut target_dir = match get_arg_flag_value("--target-dir") {
146+
Some(dir) => PathBuf::from(dir),
147+
None => metadata.target_directory.clone().into_std_path_buf(),
148+
};
149+
target_dir.push("miri");
150+
cmd.arg("--target-dir").arg(target_dir);
151+
152+
// *After* we set all the flags that need setting, forward everything else. Make sure to skip
153+
// `--target-dir` (which would otherwise be set twice).
154+
for arg in
155+
ArgSplitFlagValue::from_string_iter(&mut args, "--target-dir").filter_map(Result::err)
156+
{
157+
cmd.arg(arg);
158+
}
159+
// Forward all further arguments (not consumed by `ArgSplitFlagValue`) to cargo.
160+
cmd.args(args);
159161

160162
// Set `RUSTC_WRAPPER` to ourselves. Cargo will prepend that binary to its usual invocation,
161163
// i.e., the first argument is `rustc` -- which is what we use in `main` to distinguish

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
69fef92ab2f287f072b66fb7b4f62c8bb4acba43
1+
8b4b20836b832e91aa605a2faf5e2a55190202c8

src/concurrency/thread.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use std::cell::RefCell;
44
use std::collections::hash_map::Entry;
55
use std::num::TryFromIntError;
6+
use std::sync::atomic::{AtomicBool, Ordering::Relaxed};
67
use std::task::Poll;
78
use std::time::{Duration, SystemTime};
89

@@ -1012,8 +1013,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
10121013
/// Run the core interpreter loop. Returns only when an interrupt occurs (an error or program
10131014
/// termination).
10141015
fn run_threads(&mut self) -> InterpResult<'tcx, !> {
1016+
static SIGNALED: AtomicBool = AtomicBool::new(false);
1017+
ctrlc::set_handler(move || {
1018+
// Indicate that we have ben signaled to stop. If we were already signaled, exit
1019+
// immediately. In our interpreter loop we try to consult this value often, but if for
1020+
// whatever reason we don't get to that check or the cleanup we do upon finding that
1021+
// this bool has become true takes a long time, the exit here will promptly exit the
1022+
// process on the second Ctrl-C.
1023+
if SIGNALED.swap(true, Relaxed) {
1024+
std::process::exit(1);
1025+
}
1026+
})
1027+
.unwrap();
10151028
let this = self.eval_context_mut();
10161029
loop {
1030+
if SIGNALED.load(Relaxed) {
1031+
this.machine.handle_abnormal_termination();
1032+
std::process::exit(1);
1033+
}
10171034
match this.machine.threads.schedule(&this.machine.clock)? {
10181035
SchedulingAction::ExecuteStep => {
10191036
if !this.step()? {

src/machine.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,15 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
713713
let def_id = frame.instance.def_id();
714714
def_id.is_local() || self.local_crates.contains(&def_id.krate)
715715
}
716+
717+
/// Called when the interpreter is going to shut down abnormally, such as due to a Ctrl-C.
718+
pub(crate) fn handle_abnormal_termination(&mut self) {
719+
// All strings in the profile data are stored in a single string table which is not
720+
// written to disk until the profiler is dropped. If the interpreter exits without dropping
721+
// the profiler, it is not possible to interpret the profile data and all measureme tools
722+
// will panic when given the file.
723+
drop(self.profiler.take());
724+
}
716725
}
717726

718727
impl VisitTags for MiriMachine<'_, '_> {

src/shims/backtrace.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
102102
let ptr_layout = this.layout_of(ptr_ty)?;
103103

104104
for (i, ptr) in ptrs.into_iter().enumerate() {
105-
let offset = ptr_layout.size * i.try_into().unwrap();
105+
let offset = ptr_layout.size.checked_mul(i.try_into().unwrap(), this).unwrap();
106106

107107
let op_place = buf_place.offset(offset, ptr_layout, this)?;
108108

src/shims/foreign_items.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
166166
dependency_format.1.iter().enumerate().filter_map(|(num, &linkage)| {
167167
// We add 1 to the number because that's what rustc also does everywhere it
168168
// calls `CrateNum::new`...
169-
#[allow(clippy::integer_arithmetic)]
169+
#[allow(clippy::arithmetic_side_effects)]
170170
(linkage != Linkage::NotLinked).then_some(CrateNum::new(num + 1))
171171
}),
172172
) {
@@ -707,7 +707,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
707707
.position(|&c| c == val)
708708
{
709709
let idx = u64::try_from(idx).unwrap();
710-
#[allow(clippy::integer_arithmetic)] // idx < num, so this never wraps
710+
#[allow(clippy::arithmetic_side_effects)] // idx < num, so this never wraps
711711
let new_ptr = ptr.offset(Size::from_bytes(num - idx - 1), this)?;
712712
this.write_pointer(new_ptr, dest)?;
713713
} else {
@@ -916,10 +916,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
916916
let a = this.read_scalar(a)?.to_u64()?;
917917
let b = this.read_scalar(b)?.to_u64()?;
918918

919-
#[allow(clippy::integer_arithmetic)]
919+
#[allow(clippy::arithmetic_side_effects)]
920920
// adding two u64 and a u8 cannot wrap in a u128
921921
let wide_sum = u128::from(c_in) + u128::from(a) + u128::from(b);
922-
#[allow(clippy::integer_arithmetic)] // it's a u128, we can shift by 64
922+
#[allow(clippy::arithmetic_side_effects)] // it's a u128, we can shift by 64
923923
let (c_out, sum) = ((wide_sum >> 64).truncate::<u8>(), wide_sum.truncate::<u64>());
924924

925925
let c_out_field = this.place_field(dest, 0)?;

src/shims/intrinsics/simd.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
563563
let (op, op_len) = this.operand_to_simd(op)?;
564564
let bitmask_len = op_len.max(8);
565565

566-
assert!(dest.layout.ty.is_integral());
566+
// Returns either an unsigned integer or array of `u8`.
567+
assert!(
568+
dest.layout.ty.is_integral()
569+
|| matches!(dest.layout.ty.kind(), ty::Array(elemty, _) if elemty == &this.tcx.types.u8)
570+
);
567571
assert!(bitmask_len <= 64);
568572
assert_eq!(bitmask_len, dest.layout.size.bits());
569573
let op_len = u32::try_from(op_len).unwrap();
@@ -577,7 +581,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
577581
.unwrap();
578582
}
579583
}
580-
this.write_int(res, dest)?;
584+
// We have to force the place type to be an int so that we can write `res` into it.
585+
let mut dest = this.force_allocation(dest)?;
586+
dest.layout = this.machine.layouts.uint(dest.layout.size).unwrap();
587+
this.write_int(res, &dest.into())?;
581588
}
582589

583590
name => throw_unsup_format!("unimplemented intrinsic: `simd_{name}`"),
@@ -605,7 +612,7 @@ fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 {
605612
assert!(idx < vec_len);
606613
match endianness {
607614
Endian::Little => idx,
608-
#[allow(clippy::integer_arithmetic)] // idx < vec_len
615+
#[allow(clippy::arithmetic_side_effects)] // idx < vec_len
609616
Endian::Big => vec_len - 1 - idx, // reverse order of bits
610617
}
611618
}

0 commit comments

Comments
 (0)