1
Fork 0

implement __rust_maybe_catch_panic

This commit is contained in:
Ralf Jung 2017-05-26 17:27:39 -07:00
parent 55438fe5bf
commit 720c5f874e
2 changed files with 43 additions and 5 deletions

View file

@ -456,9 +456,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
// An external C function
let ty = sig.output();
let (ret, target) = destination.unwrap();
self.call_c_abi(instance.def_id(), arg_operands, ret, ty)?;
self.dump_local(ret);
self.goto_block(target);
self.call_c_abi(instance.def_id(), arg_operands, ret, ty, target)?;
return Ok(());
}
@ -493,6 +491,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
arg_operands: &[mir::Operand<'tcx>],
dest: Lvalue<'tcx>,
dest_ty: Ty<'tcx>,
dest_block: mir::BasicBlock,
) -> EvalResult<'tcx> {
let name = self.tcx.item_name(def_id);
let attrs = self.tcx.get_attrs(def_id);
@ -539,6 +538,34 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
}
"__rust_maybe_catch_panic" => {
// We abort on panic, so not much is going on here, but we still have to call the closure
let u8_ptr_ty = self.tcx.mk_mut_ptr(self.tcx.types.u8);
let f = args[0].read_ptr(&self.memory)?;
let data = args[1].read_ptr(&self.memory)?; // FIXME: Why does value_to_primval(args[2], u8_ptr_ty)?.to_ptr()? here end up doing the Wrong Thing (TM)?
let f_instance = self.memory.get_fn(f.alloc_id)?;
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
// Now we make a functon call. TODO: Consider making this re-usable? EvalContext::step does sth. similar for the TLS dtors,
// and of coruse eval_main.
let mir = self.load_mir(f_instance.def)?;
self.push_stack_frame(
f_instance,
mir.span,
mir,
Lvalue::from_ptr(Pointer::zst_ptr()),
StackPopCleanup::Goto(dest_block),
)?;
let arg_local = self.frame().mir.args_iter().next().ok_or(EvalError::AbiViolation("Argument to __rust_maybe_catch_panic does not take enough arguments.".to_owned()))?;
let dest = self.eval_lvalue(&mir::Lvalue::Local(arg_local))?;
self.write_value(Value::ByVal(PrimVal::Ptr(data)), dest, u8_ptr_ty)?;
// Don't fall through
// FIXME: Do we have to do self.dump_local(ret) anywhere?
return Ok(());
}
"memcmp" => {
let left = args[0].read_ptr(&self.memory)?;
let right = args[1].read_ptr(&self.memory)?;
@ -684,6 +711,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
// Since we pushed no stack frame, the main loop will act
// as if the call just completed and it's returning to the
// current frame.
self.dump_local(dest);
self.goto_block(dest_block);
Ok(())
}
}

9
tests/run-pass/catch.rs Normal file
View file

@ -0,0 +1,9 @@
use std::panic::{catch_unwind, AssertUnwindSafe};
fn main() {
let mut i = 3;
let _ = catch_unwind(AssertUnwindSafe(|| {i -= 2;} ));
for _ in 0..i {
println!("I");
}
}