Skip to content

Commit 2d4ebf0

Browse files
authored
Merge pull request #610 from RalfJung/panic
Support panic_impl and atomic_nand
2 parents 9e0e219 + 48ac35f commit 2d4ebf0

File tree

6 files changed

+53
-20
lines changed

6 files changed

+53
-20
lines changed

src/fn_call.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
3939
if this.tcx.is_foreign_item(instance.def_id()) {
4040
// An external function that we cannot find MIR for, but we can still run enough
4141
// of them to make miri viable.
42-
this.emulate_foreign_item(
43-
instance.def_id(),
44-
args,
45-
dest.unwrap(),
46-
ret.unwrap(),
47-
)?;
42+
this.emulate_foreign_item(instance.def_id(), args, dest, ret)?;
4843
// `goto_block` already handled
4944
return Ok(None);
5045
}
@@ -59,8 +54,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
5954
&mut self,
6055
def_id: DefId,
6156
args: &[OpTy<'tcx, Borrow>],
62-
dest: PlaceTy<'tcx, Borrow>,
63-
ret: mir::BasicBlock,
57+
dest: Option<PlaceTy<'tcx, Borrow>>,
58+
ret: Option<mir::BasicBlock>,
6459
) -> EvalResult<'tcx> {
6560
let this = self.eval_context_mut();
6661
let attrs = this.tcx.get_attrs(def_id);
@@ -70,9 +65,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
7065
};
7166
// Strip linker suffixes (seen on 32bit macOS)
7267
let link_name = link_name.trim_end_matches("$UNIX2003");
73-
7468
let tcx = &{this.tcx.tcx};
7569

70+
// first: functions that could diverge
71+
match &link_name[..] {
72+
"__rust_start_panic" | "panic_impl" => {
73+
return err!(MachineError("the evaluated program panicked".to_string()));
74+
}
75+
_ => if dest.is_none() {
76+
return err!(Unimplemented(
77+
format!("can't call diverging foreign function: {}", link_name),
78+
));
79+
}
80+
}
81+
82+
// now: functions that assume a ret and dest
83+
let dest = dest.expect("we already checked for a dest");
84+
let ret = ret.expect("dest is Some but ret is None");
7685
match &link_name[..] {
7786
"malloc" => {
7887
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,
245254
return Ok(());
246255
}
247256

248-
"__rust_start_panic" =>
249-
return err!(MachineError("the evaluated program panicked".to_string())),
250-
251257
"memcmp" => {
252258
let left = this.read_scalar(args[0])?.not_undef()?;
253259
let right = this.read_scalar(args[1])?.not_undef()?;

src/intrinsic.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,11 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
108108
"atomic_and_rel" |
109109
"atomic_and_acqrel" |
110110
"atomic_and_relaxed" |
111+
"atomic_nand" |
112+
"atomic_nand_acq" |
113+
"atomic_nand_rel" |
114+
"atomic_nand_acqrel" |
115+
"atomic_nand_relaxed" |
111116
"atomic_xadd" |
112117
"atomic_xadd_acq" |
113118
"atomic_xadd_rel" |
@@ -125,16 +130,23 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a,
125130
let rhs = this.read_immediate(args[1])?;
126131
let old = this.read_immediate(ptr.into())?;
127132
this.write_immediate(*old, dest)?; // old value is returned
128-
let op = match intrinsic_name.split('_').nth(1).unwrap() {
129-
"or" => mir::BinOp::BitOr,
130-
"xor" => mir::BinOp::BitXor,
131-
"and" => mir::BinOp::BitAnd,
132-
"xadd" => mir::BinOp::Add,
133-
"xsub" => mir::BinOp::Sub,
133+
let (op, neg) = match intrinsic_name.split('_').nth(1).unwrap() {
134+
"or" => (mir::BinOp::BitOr, false),
135+
"xor" => (mir::BinOp::BitXor, false),
136+
"and" => (mir::BinOp::BitAnd, false),
137+
"xadd" => (mir::BinOp::Add, false),
138+
"xsub" => (mir::BinOp::Sub, false),
139+
"nand" => (mir::BinOp::BitAnd, true),
134140
_ => bug!(),
135141
};
136142
// Atomics wrap around on overflow.
137-
this.binop_ignore_overflow(op, old, rhs, ptr.into())?;
143+
let (val, _overflowed) = this.binary_op_imm(op, old, rhs)?;
144+
let val = if neg {
145+
this.unary_op(mir::UnOp::Not, val, old.layout)?
146+
} else {
147+
val
148+
};
149+
this.write_scalar(val, ptr.into())?;
138150
}
139151

140152
"breakpoint" => unimplemented!(), // halt miri
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
//error-pattern: the evaluated program panicked
22

33
fn main() {
4-
assert_eq!(5, 6);
4+
std::panic!("panicking from libstd");
55
}

tests/compile-fail/panic2.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//error-pattern: the evaluated program panicked
2+
3+
fn main() {
4+
std::panic!("{}-panicking from libstd", 42);
5+
}

tests/compile-fail/panic3.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//error-pattern: the evaluated program panicked
2+
3+
fn main() {
4+
core::panic!("panicking from libcore");
5+
}

tests/compile-fail/panic4.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//error-pattern: the evaluated program panicked
2+
3+
fn main() {
4+
core::panic!("{}-panicking from libcore", 42);
5+
}

0 commit comments

Comments
 (0)