Skip to content

Commit 23fd3ce

Browse files
author
hyd-dev
committed
Merge branch 'rlib' into doctest
2 parents 10345ff + 0737de8 commit 23fd3ce

37 files changed

+237
-130
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,10 @@ up the sysroot. If you are using `miri` (the Miri driver) directly, see the
195195
Miri adds its own set of `-Z` flags, which are usually set via the `MIRIFLAGS`
196196
environment variable:
197197

198+
* `-Zmiri-compare-exchange-weak-failure-rate=<rate>` changes the failure rate of
199+
`compare_exchange_weak` operations. The default is `0.8` (so 4 out of 5 weak ops will fail).
200+
You can change it to any value between `0.0` and `1.0`, where `1.0` means it
201+
will always fail and `0.0` means it will never fail.
198202
* `-Zmiri-disable-alignment-check` disables checking pointer alignment, so you
199203
can focus on other failures, but it means Miri can miss bugs in your program.
200204
Using this flag is **unsound**.

cargo-miri/bin.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -625,16 +625,13 @@ fn phase_cargo_rustc(args: env::Args) {
625625
let target_crate = is_target_crate();
626626
let print = get_arg_flag_value("--print").is_some(); // whether this is cargo passing `--print` to get some infos
627627

628-
// rlib and cdylib are just skipped, we cannot interpret them and do not need them
628+
// cdylib is just skipped, we cannot interpret it and do not need it
629629
// for the rest of the build either.
630-
match get_arg_flag_value("--crate-type").as_deref() {
631-
Some("rlib") | Some("cdylib") => {
632-
if verbose {
633-
eprint!("[cargo-miri rustc] (rlib/cdylib skipped)");
634-
}
635-
return;
630+
if get_arg_flag_value("--crate-type").as_deref() == Some("cdylib") {
631+
if verbose {
632+
eprint!("[cargo-miri rustc] (cdylib skipped)");
636633
}
637-
_ => {},
634+
return;
638635
}
639636

640637
let store_json = |info: &CrateRunInfo| {

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
78e22069d018e83915201c8a218a0a94227f6420
1+
bb587b1a1737738658d2eaecd4c8c1cab555257a

src/bin/miri.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,10 @@ fn main() {
230230
err => panic!("unknown error decoding -Zmiri-seed as hex: {:?}", err),
231231
});
232232
if seed_raw.len() > 8 {
233-
panic!(format!(
233+
panic!(
234234
"-Zmiri-seed must be at most 8 bytes, was {}",
235235
seed_raw.len()
236-
));
236+
);
237237
}
238238

239239
let mut bytes = [0; 8];
@@ -282,6 +282,14 @@ fn main() {
282282
};
283283
miri_config.tracked_alloc_id = Some(miri::AllocId(id));
284284
}
285+
arg if arg.starts_with("-Zmiri-compare-exchange-weak-failure-rate=") => {
286+
let rate = match arg.strip_prefix("-Zmiri-compare-exchange-weak-failure-rate=").unwrap().parse::<f64>() {
287+
Ok(rate) if rate >= 0.0 && rate <= 1.0 => rate,
288+
Ok(_) => panic!("-Zmiri-compare-exchange-weak-failure-rate must be between `0.0` and `1.0`"),
289+
Err(err) => panic!("-Zmiri-compare-exchange-weak-failure-rate requires a `f64` between `0.0` and `1.0`: {}", err),
290+
};
291+
miri_config.cmpxchg_weak_failure_rate = rate;
292+
}
285293
_ => {
286294
// Forward to rustc.
287295
rustc_args.push(arg);

src/data_race.rs

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ use rustc_target::abi::Size;
7575

7676
use crate::{
7777
ImmTy, Immediate, InterpResult, MPlaceTy, MemPlaceMeta, MiriEvalContext, MiriEvalContextExt,
78-
OpTy, Pointer, RangeMap, ScalarMaybeUninit, Tag, ThreadId, VClock, VTimestamp,
78+
OpTy, Pointer, RangeMap, Scalar, ScalarMaybeUninit, Tag, ThreadId, VClock, VTimestamp,
7979
VectorIdx, MemoryKind, MiriMemoryKind
8080
};
8181

@@ -544,31 +544,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
544544

545545
/// Perform an atomic compare and exchange at a given memory location.
546546
/// On success an atomic RMW operation is performed and on failure
547-
/// only an atomic read occurs.
547+
/// only an atomic read occurs. If `can_fail_spuriously` is true,
548+
/// then we treat it as a "compare_exchange_weak" operation, and
549+
/// some portion of the time fail even when the values are actually
550+
/// identical.
548551
fn atomic_compare_exchange_scalar(
549552
&mut self,
550553
place: MPlaceTy<'tcx, Tag>,
551554
expect_old: ImmTy<'tcx, Tag>,
552555
new: ScalarMaybeUninit<Tag>,
553556
success: AtomicRwOp,
554557
fail: AtomicReadOp,
558+
can_fail_spuriously: bool,
555559
) -> InterpResult<'tcx, Immediate<Tag>> {
560+
use rand::Rng as _;
556561
let this = self.eval_context_mut();
557562

558563
// Failure ordering cannot be stronger than success ordering, therefore first attempt
559564
// to read with the failure ordering and if successful then try again with the success
560565
// read ordering and write in the success case.
561566
// Read as immediate for the sake of `binary_op()`
562567
let old = this.allow_data_races_mut(|this| this.read_immediate(place.into()))?;
563-
564568
// `binary_op` will bail if either of them is not a scalar.
565569
let eq = this.overflowing_binary_op(mir::BinOp::Eq, old, expect_old)?.0;
566-
let res = Immediate::ScalarPair(old.to_scalar_or_uninit(), eq.into());
570+
// If the operation would succeed, but is "weak", fail some portion
571+
// of the time, based on `rate`.
572+
let rate = this.memory.extra.cmpxchg_weak_failure_rate;
573+
let cmpxchg_success = eq.to_bool()?
574+
&& (!can_fail_spuriously || this.memory.extra.rng.borrow_mut().gen::<f64>() < rate);
575+
let res = Immediate::ScalarPair(
576+
old.to_scalar_or_uninit(),
577+
Scalar::from_bool(cmpxchg_success).into(),
578+
);
567579

568580
// Update ptr depending on comparison.
569581
// if successful, perform a full rw-atomic validation
570582
// otherwise treat this as an atomic load with the fail ordering.
571-
if eq.to_bool()? {
583+
if cmpxchg_success {
572584
this.allow_data_races_mut(|this| this.write_scalar(new, place.into()))?;
573585
this.validate_atomic_rmw(place, success)?;
574586
} else {

src/eval.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ pub struct MiriConfig {
5050
pub track_raw: bool,
5151
/// Determine if data race detection should be enabled
5252
pub data_race_detector: bool,
53+
/// Rate of spurious failures for compare_exchange_weak atomic operations,
54+
/// between 0.0 and 1.0, defaulting to 0.8 (80% chance of failure).
55+
pub cmpxchg_weak_failure_rate: f64,
5356
}
5457

5558
impl Default for MiriConfig {
@@ -68,6 +71,7 @@ impl Default for MiriConfig {
6871
tracked_alloc_id: None,
6972
track_raw: false,
7073
data_race_detector: true,
74+
cmpxchg_weak_failure_rate: 0.8,
7175
}
7276
}
7377
}

src/helpers.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::mir;
99
use rustc_middle::ty::{self, List, TyCtxt, layout::TyAndLayout};
1010
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
1111
use rustc_target::abi::{LayoutOf, Size, FieldsShape, Variants};
12+
use rustc_target::spec::abi::Abi;
1213

1314
use rand::RngCore;
1415

@@ -553,6 +554,15 @@ pub fn check_arg_count<'a, 'tcx, const N: usize>(args: &'a [OpTy<'tcx, Tag>]) ->
553554
throw_ub_format!("incorrect number of arguments: got {}, expected {}", args.len(), N)
554555
}
555556

557+
/// Check that the ABI is what we expect.
558+
pub fn check_abi<'a>(abi: Abi, exp_abi: Abi) -> InterpResult<'a, ()> {
559+
if abi == exp_abi {
560+
Ok(())
561+
} else {
562+
throw_ub_format!("calling a function with ABI {:?} using caller ABI {:?}", exp_abi, abi)
563+
}
564+
}
565+
556566
pub fn isolation_error(name: &str) -> InterpResult<'static> {
557567
throw_machine_stop!(TerminationInfo::UnsupportedInIsolation(format!(
558568
"{} not available when isolation is enabled",

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
#![warn(rust_2018_idioms)]
99
#![allow(clippy::cast_lossless)]
1010

11-
extern crate rustc_attr;
1211
extern crate rustc_apfloat;
1312
extern crate rustc_ast;
1413
#[macro_use] extern crate rustc_middle;

src/machine.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ pub struct MemoryExtra {
135135

136136
/// Controls whether alignment of memory accesses is being checked.
137137
pub(crate) check_alignment: AlignmentCheck,
138+
139+
/// Failure rate of compare_exchange_weak, between 0.0 and 1.0
140+
pub(crate) cmpxchg_weak_failure_rate: f64,
138141
}
139142

140143
impl MemoryExtra {
@@ -162,6 +165,7 @@ impl MemoryExtra {
162165
rng: RefCell::new(rng),
163166
tracked_alloc_id: config.tracked_alloc_id,
164167
check_alignment: config.check_alignment,
168+
cmpxchg_weak_failure_rate: config.cmpxchg_weak_failure_rate,
165169
}
166170
}
167171

@@ -353,24 +357,24 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
353357
fn find_mir_or_eval_fn(
354358
ecx: &mut InterpCx<'mir, 'tcx, Self>,
355359
instance: ty::Instance<'tcx>,
356-
_abi: Abi,
360+
abi: Abi,
357361
args: &[OpTy<'tcx, Tag>],
358362
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
359363
unwind: Option<mir::BasicBlock>,
360364
) -> InterpResult<'tcx, Option<&'mir mir::Body<'tcx>>> {
361-
ecx.find_mir_or_eval_fn(instance, args, ret, unwind)
365+
ecx.find_mir_or_eval_fn(instance, abi, args, ret, unwind)
362366
}
363367

364368
#[inline(always)]
365369
fn call_extra_fn(
366370
ecx: &mut InterpCx<'mir, 'tcx, Self>,
367371
fn_val: Dlsym,
368-
_abi: Abi,
372+
abi: Abi,
369373
args: &[OpTy<'tcx, Tag>],
370374
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
371375
_unwind: Option<mir::BasicBlock>,
372376
) -> InterpResult<'tcx> {
373-
ecx.call_dlsym(fn_val, args, ret)
377+
ecx.call_dlsym(fn_val, abi, args, ret)
374378
}
375379

376380
#[inline(always)]

src/shims/dlsym.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use rustc_middle::mir;
2+
use rustc_target::spec::abi::Abi;
23

34
use crate::*;
45
use shims::posix::dlsym as posix;
@@ -29,13 +30,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
2930
fn call_dlsym(
3031
&mut self,
3132
dlsym: Dlsym,
33+
abi: Abi,
3234
args: &[OpTy<'tcx, Tag>],
3335
ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>,
3436
) -> InterpResult<'tcx> {
3537
let this = self.eval_context_mut();
3638
match dlsym {
37-
Dlsym::Posix(dlsym) => posix::EvalContextExt::call_dlsym(this, dlsym, args, ret),
38-
Dlsym::Windows(dlsym) => windows::EvalContextExt::call_dlsym(this, dlsym, args, ret),
39+
Dlsym::Posix(dlsym) => posix::EvalContextExt::call_dlsym(this, dlsym, abi, args, ret),
40+
Dlsym::Windows(dlsym) => windows::EvalContextExt::call_dlsym(this, dlsym, abi, args, ret),
3941
}
4042
}
4143
}

0 commit comments

Comments
 (0)