Merge pull request #610 from RalfJung/panic
Support panic_impl and atomic_nand
This commit is contained in:
commit
2d4ebf017d
@ -39,12 +39,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
|
|||||||
if this.tcx.is_foreign_item(instance.def_id()) {
|
if this.tcx.is_foreign_item(instance.def_id()) {
|
||||||
// An external function that we cannot find MIR for, but we can still run enough
|
// An external function that we cannot find MIR for, but we can still run enough
|
||||||
// of them to make miri viable.
|
// of them to make miri viable.
|
||||||
this.emulate_foreign_item(
|
this.emulate_foreign_item(instance.def_id(), args, dest, ret)?;
|
||||||
instance.def_id(),
|
|
||||||
args,
|
|
||||||
dest.unwrap(),
|
|
||||||
ret.unwrap(),
|
|
||||||
)?;
|
|
||||||
// `goto_block` already handled
|
// `goto_block` already handled
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
@ -59,8 +54,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
|
|||||||
&mut self,
|
&mut self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
args: &[OpTy<'tcx, Borrow>],
|
args: &[OpTy<'tcx, Borrow>],
|
||||||
dest: PlaceTy<'tcx, Borrow>,
|
dest: Option<PlaceTy<'tcx, Borrow>>,
|
||||||
ret: mir::BasicBlock,
|
ret: Option<mir::BasicBlock>,
|
||||||
) -> EvalResult<'tcx> {
|
) -> EvalResult<'tcx> {
|
||||||
let this = self.eval_context_mut();
|
let this = self.eval_context_mut();
|
||||||
let attrs = this.tcx.get_attrs(def_id);
|
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)
|
// Strip linker suffixes (seen on 32bit macOS)
|
||||||
let link_name = link_name.trim_end_matches("$UNIX2003");
|
let link_name = link_name.trim_end_matches("$UNIX2003");
|
||||||
|
|
||||||
let tcx = &{this.tcx.tcx};
|
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[..] {
|
match &link_name[..] {
|
||||||
"malloc" => {
|
"malloc" => {
|
||||||
let size = this.read_scalar(args[0])?.to_usize(this)?;
|
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(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
"__rust_start_panic" =>
|
|
||||||
return err!(MachineError("the evaluated program panicked".to_string())),
|
|
||||||
|
|
||||||
"memcmp" => {
|
"memcmp" => {
|
||||||
let left = this.read_scalar(args[0])?.not_undef()?;
|
let left = this.read_scalar(args[0])?.not_undef()?;
|
||||||
let right = this.read_scalar(args[1])?.not_undef()?;
|
let right = this.read_scalar(args[1])?.not_undef()?;
|
||||||
|
@ -108,6 +108,11 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
|
|||||||
"atomic_and_rel" |
|
"atomic_and_rel" |
|
||||||
"atomic_and_acqrel" |
|
"atomic_and_acqrel" |
|
||||||
"atomic_and_relaxed" |
|
"atomic_and_relaxed" |
|
||||||
|
"atomic_nand" |
|
||||||
|
"atomic_nand_acq" |
|
||||||
|
"atomic_nand_rel" |
|
||||||
|
"atomic_nand_acqrel" |
|
||||||
|
"atomic_nand_relaxed" |
|
||||||
"atomic_xadd" |
|
"atomic_xadd" |
|
||||||
"atomic_xadd_acq" |
|
"atomic_xadd_acq" |
|
||||||
"atomic_xadd_rel" |
|
"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 rhs = this.read_immediate(args[1])?;
|
||||||
let old = this.read_immediate(ptr.into())?;
|
let old = this.read_immediate(ptr.into())?;
|
||||||
this.write_immediate(*old, dest)?; // old value is returned
|
this.write_immediate(*old, dest)?; // old value is returned
|
||||||
let op = match intrinsic_name.split('_').nth(1).unwrap() {
|
let (op, neg) = match intrinsic_name.split('_').nth(1).unwrap() {
|
||||||
"or" => mir::BinOp::BitOr,
|
"or" => (mir::BinOp::BitOr, false),
|
||||||
"xor" => mir::BinOp::BitXor,
|
"xor" => (mir::BinOp::BitXor, false),
|
||||||
"and" => mir::BinOp::BitAnd,
|
"and" => (mir::BinOp::BitAnd, false),
|
||||||
"xadd" => mir::BinOp::Add,
|
"xadd" => (mir::BinOp::Add, false),
|
||||||
"xsub" => mir::BinOp::Sub,
|
"xsub" => (mir::BinOp::Sub, false),
|
||||||
|
"nand" => (mir::BinOp::BitAnd, true),
|
||||||
_ => bug!(),
|
_ => bug!(),
|
||||||
};
|
};
|
||||||
// Atomics wrap around on overflow.
|
// 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
|
"breakpoint" => unimplemented!(), // halt miri
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
//error-pattern: the evaluated program panicked
|
//error-pattern: the evaluated program panicked
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(5, 6);
|
std::panic!("panicking from libstd");
|
||||||
}
|
}
|
5
tests/compile-fail/panic2.rs
Normal file
5
tests/compile-fail/panic2.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//error-pattern: the evaluated program panicked
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
std::panic!("{}-panicking from libstd", 42);
|
||||||
|
}
|
5
tests/compile-fail/panic3.rs
Normal file
5
tests/compile-fail/panic3.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//error-pattern: the evaluated program panicked
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
core::panic!("panicking from libcore");
|
||||||
|
}
|
5
tests/compile-fail/panic4.rs
Normal file
5
tests/compile-fail/panic4.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
//error-pattern: the evaluated program panicked
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
core::panic!("{}-panicking from libcore", 42);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user