From 661ed7b82dc7b9ab597a274f10055f58f9db6f4b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Feb 2019 11:38:40 +0100 Subject: [PATCH 1/2] implement atomic_nand --- src/intrinsic.rs | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 0ef847236418..b7c5d8d07c25 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -108,6 +108,11 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, "atomic_and_rel" | "atomic_and_acqrel" | "atomic_and_relaxed" | + "atomic_nand" | + "atomic_nand_acq" | + "atomic_nand_rel" | + "atomic_nand_acqrel" | + "atomic_nand_relaxed" | "atomic_xadd" | "atomic_xadd_acq" | "atomic_xadd_rel" | @@ -125,16 +130,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, let rhs = this.read_immediate(args[1])?; let old = this.read_immediate(ptr.into())?; this.write_immediate(*old, dest)?; // old value is returned - let op = match intrinsic_name.split('_').nth(1).unwrap() { - "or" => mir::BinOp::BitOr, - "xor" => mir::BinOp::BitXor, - "and" => mir::BinOp::BitAnd, - "xadd" => mir::BinOp::Add, - "xsub" => mir::BinOp::Sub, + let (op, neg) = match intrinsic_name.split('_').nth(1).unwrap() { + "or" => (mir::BinOp::BitOr, false), + "xor" => (mir::BinOp::BitXor, false), + "and" => (mir::BinOp::BitAnd, false), + "xadd" => (mir::BinOp::Add, false), + "xsub" => (mir::BinOp::Sub, false), + "nand" => (mir::BinOp::BitAnd, true), _ => bug!(), }; // Atomics wrap around on overflow. - this.binop_ignore_overflow(op, old, rhs, ptr.into())?; + let (val, _overflowed) = this.binary_op_imm(op, old, rhs)?; + let val = if neg { + this.unary_op(mir::UnOp::Not, val, old.layout)? + } else { + val + }; + this.write_scalar(val, ptr.into())?; } "breakpoint" => unimplemented!(), // halt miri From 48ac35f0727e1c660fa95012a941cf65de8b9443 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Feb 2019 11:39:16 +0100 Subject: [PATCH 2/2] panic_impl is another way to panic --- src/fn_call.rs | 30 +++++++++++++--------- tests/compile-fail/{panic.rs => panic1.rs} | 2 +- tests/compile-fail/panic2.rs | 5 ++++ tests/compile-fail/panic3.rs | 5 ++++ tests/compile-fail/panic4.rs | 5 ++++ 5 files changed, 34 insertions(+), 13 deletions(-) rename tests/compile-fail/{panic.rs => panic1.rs} (60%) create mode 100644 tests/compile-fail/panic2.rs create mode 100644 tests/compile-fail/panic3.rs create mode 100644 tests/compile-fail/panic4.rs diff --git a/src/fn_call.rs b/src/fn_call.rs index 720737b53965..abb239ad7d62 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -39,12 +39,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, if this.tcx.is_foreign_item(instance.def_id()) { // An external function that we cannot find MIR for, but we can still run enough // of them to make miri viable. - this.emulate_foreign_item( - instance.def_id(), - args, - dest.unwrap(), - ret.unwrap(), - )?; + this.emulate_foreign_item(instance.def_id(), args, dest, ret)?; // `goto_block` already handled return Ok(None); } @@ -59,8 +54,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, &mut self, def_id: DefId, args: &[OpTy<'tcx, Borrow>], - dest: PlaceTy<'tcx, Borrow>, - ret: mir::BasicBlock, + dest: Option>, + ret: Option, ) -> EvalResult<'tcx> { let this = self.eval_context_mut(); let attrs = this.tcx.get_attrs(def_id); @@ -70,9 +65,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, }; // Strip linker suffixes (seen on 32bit macOS) let link_name = link_name.trim_end_matches("$UNIX2003"); - let tcx = &{this.tcx.tcx}; + // first: functions that could diverge + match &link_name[..] { + "__rust_start_panic" | "panic_impl" => { + return err!(MachineError("the evaluated program panicked".to_string())); + } + _ => if dest.is_none() { + return err!(Unimplemented( + format!("can't call diverging foreign function: {}", link_name), + )); + } + } + + // now: functions that assume a ret and dest + let dest = dest.expect("we already checked for a dest"); + let ret = ret.expect("dest is Some but ret is None"); match &link_name[..] { "malloc" => { let size = this.read_scalar(args[0])?.to_usize(this)?; @@ -245,9 +254,6 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, return Ok(()); } - "__rust_start_panic" => - return err!(MachineError("the evaluated program panicked".to_string())), - "memcmp" => { let left = this.read_scalar(args[0])?.not_undef()?; let right = this.read_scalar(args[1])?.not_undef()?; diff --git a/tests/compile-fail/panic.rs b/tests/compile-fail/panic1.rs similarity index 60% rename from tests/compile-fail/panic.rs rename to tests/compile-fail/panic1.rs index 0d594f9bd4c3..1163c8708287 100644 --- a/tests/compile-fail/panic.rs +++ b/tests/compile-fail/panic1.rs @@ -1,5 +1,5 @@ //error-pattern: the evaluated program panicked fn main() { - assert_eq!(5, 6); + std::panic!("panicking from libstd"); } diff --git a/tests/compile-fail/panic2.rs b/tests/compile-fail/panic2.rs new file mode 100644 index 000000000000..e643e6922413 --- /dev/null +++ b/tests/compile-fail/panic2.rs @@ -0,0 +1,5 @@ +//error-pattern: the evaluated program panicked + +fn main() { + std::panic!("{}-panicking from libstd", 42); +} diff --git a/tests/compile-fail/panic3.rs b/tests/compile-fail/panic3.rs new file mode 100644 index 000000000000..b22f95d9c69d --- /dev/null +++ b/tests/compile-fail/panic3.rs @@ -0,0 +1,5 @@ +//error-pattern: the evaluated program panicked + +fn main() { + core::panic!("panicking from libcore"); +} diff --git a/tests/compile-fail/panic4.rs b/tests/compile-fail/panic4.rs new file mode 100644 index 000000000000..449e716e161c --- /dev/null +++ b/tests/compile-fail/panic4.rs @@ -0,0 +1,5 @@ +//error-pattern: the evaluated program panicked + +fn main() { + core::panic!("{}-panicking from libcore", 42); +}