implement __rust_maybe_catch_panic
This commit is contained in:
parent
55438fe5bf
commit
720c5f874e
2 changed files with 43 additions and 5 deletions
|
@ -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
9
tests/run-pass/catch.rs
Normal 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");
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue