Skip to content

Commit

Permalink
Get it working
Browse files Browse the repository at this point in the history
  • Loading branch information
Aaron1011 committed May 29, 2019
1 parent e1c42e5 commit 6d195bc
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 12 deletions.
22 changes: 17 additions & 5 deletions src/fn_call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
unwind: Option<mir::BasicBlock>
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
let this = self.eval_context_mut();
trace!("eval_fn_call: {:#?}, {:?} {:?}", instance, instance.def_id(), dest.map(|place| *place));
Expand Down Expand Up @@ -48,7 +49,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
if this.tcx.is_foreign_item(instance.def_id()) {
// An external function that we (possibly) cannot find MIR for, but we can still run enough
// of them to make miri viable.
return Ok(this.emulate_foreign_item(instance, args, dest, ret)?);
return Ok(this.emulate_foreign_item(instance, args, dest, ret, unwind)?);
}

// Otherwise, load the MIR.
Expand Down Expand Up @@ -143,6 +144,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
unwind: Option<mir::BasicBlock>
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
let def_id = instance.def_id();
let this = self.eval_context_mut();
Expand Down Expand Up @@ -220,6 +222,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
return err!(MachineError("the evaluated program abort-panicked".to_string()));
}

//this.machine.unwinding = true;

// This part is tricky - we need to call BoxMeUp::box_me_up
// on the vtable.
//
Expand Down Expand Up @@ -281,6 +285,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
// '*mut (dyn Any + Send)', which is a fat

let temp_ptr = this.allocate(dyn_ptr_layout, MiriMemoryKind::UnwindHelper.into());
this.machine.box_me_up_tmp_ptr = Some(temp_ptr.clone());


// Keep track of our current frame
// This allows us to step throgh the exection of 'box_me_up',
Expand All @@ -292,14 +298,19 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
box_me_up_mir.span,
box_me_up_mir,
Some(temp_ptr.into()),
StackPopCleanup::None { cleanup: true, unwind: None }
// We know that this frame will always be unwound,
// since we enable unwinding as soon as we encounter it
// in Evaluator::stack_pop
StackPopCleanup::Goto { ret: None, unwind }
)?;

this.frame_mut().extra.is_box_me_frame = true;

let mut args = this.frame().mir.args_iter();
let arg_0 = this.eval_place(&mir::Place::Base(mir::PlaceBase::Local(args.next().unwrap())))?;
this.write_scalar(data_ptr, arg_0)?;

// Step through execution of 'box_me_up'
/*// Step through execution of 'box_me_up'
// We know that we're finished when our stack depth
// returns to where it was before.
//
Expand Down Expand Up @@ -343,7 +354,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
unwind_stack(this, real_ret_data, real_ret_vtable)?;
this.memory_mut().deallocate(temp_ptr.to_ptr()?, None, MiriMemoryKind::UnwindHelper.into())?;
this.dump_place(*dest.expect("dest is None!"));
this.dump_place(*dest.expect("dest is None!"));*/

return Ok(None)

Expand Down Expand Up @@ -551,7 +562,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
data_ptr,
vtable_ptr,
dest: dest.clone(),
ret
ret,
})
}

Expand Down Expand Up @@ -1177,6 +1188,7 @@ fn unwind_stack<'a, 'mir, 'tcx>(
// with 'catch_panic'. When we find this marker, we've found
// our target frame to jump to.
if let Some(unwind_data) = this.frame_mut().extra.catch_panic.take() {

trace!("unwinding: found target frame: {:?}", this.frame().span);

let data_ptr = unwind_data.data_ptr.clone();
Expand Down
4 changes: 3 additions & 1 deletion src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<'
for item in mem::replace(&mut items, Default::default()).iter() {
if item.ident.name.as_str() == *segment {
if path_it.peek().is_none() {
return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()).def_id());
return Some(item.res.def_id())
//eprintln!("Generics: {:?}", this.tcx.generics_of(item.res.def_id()));
//return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()).def_id());
}

items = this.tcx.item_children(item.res.def_id());
Expand Down
67 changes: 61 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,8 @@ pub struct Evaluator<'tcx> {

/// Whether or not we are currently unwinding from
/// a panic
pub(crate) unwinding: bool
pub(crate) unwinding: bool,
pub(crate) box_me_up_tmp_ptr: Option<MPlaceTy<'tcx, Tag>>
}

pub struct CachedTypes<'tcx> {
Expand All @@ -399,7 +400,8 @@ impl<'tcx> Evaluator<'tcx> {
validate,
rng: seed.map(|s| StdRng::seed_from_u64(s)),
cached_data: None,
unwinding: false
unwinding: false,
box_me_up_tmp_ptr: None
}
}
}
Expand All @@ -426,7 +428,8 @@ impl<'a, 'mir, 'tcx> MiriEvalContextExt<'a, 'mir, 'tcx> for MiriEvalContext<'a,

pub struct FrameData<'tcx> {
pub call_id: stacked_borrows::CallId,
pub catch_panic: Option<UnwindData<'tcx>>
pub catch_panic: Option<UnwindData<'tcx>>,
pub is_box_me_frame: bool
}

/// Hold all of the relevant data for a call to
Expand All @@ -439,7 +442,7 @@ pub struct UnwindData<'tcx> {
pub data_ptr: MPlaceTy<'tcx, Tag>,
pub vtable_ptr: MPlaceTy<'tcx, Tag>,
pub dest: PlaceTy<'tcx, Tag>,
pub ret: mir::BasicBlock
pub ret: mir::BasicBlock,
}

impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
Expand Down Expand Up @@ -467,8 +470,9 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
args: &[OpTy<'tcx, Tag>],
dest: Option<PlaceTy<'tcx, Tag>>,
ret: Option<mir::BasicBlock>,
unwind: Option<mir::BasicBlock>
) -> EvalResult<'tcx, Option<&'mir mir::Mir<'tcx>>> {
ecx.find_fn(instance, args, dest, ret)
ecx.find_fn(instance, args, dest, ret, unwind)
}

#[inline(always)]
Expand Down Expand Up @@ -633,7 +637,8 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
) -> EvalResult<'tcx, FrameData<'tcx>> {
Ok(FrameData {
call_id: ecx.memory().extra.borrow_mut().new_call(),
catch_panic: None
catch_panic: None,
is_box_me_frame: false
})
}

Expand All @@ -642,6 +647,56 @@ impl<'a, 'mir, 'tcx> Machine<'a, 'mir, 'tcx> for Evaluator<'tcx> {
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
extra: FrameData,
) -> EvalResult<'tcx, StackPopInfo> {
if extra.is_box_me_frame {
trace!("unwinding: found box_me_frame");
ecx.machine.unwinding = true;
}
if ecx.machine.unwinding {
trace!("Popping during unwind!");
if let Some(unwind_data) = ecx.frame_mut().extra.catch_panic.take() {
// We've just popped the frame that was immediately above
// our target frame on the stack.
//
trace!("unwinding: found target frame: {:?}", ecx.frame().span);

// 'box_me_up' has finished. 'temp_ptr' now holds
// a '*mut (dyn Any + Send)'
// We want to split this into its consituient parts -
// the data and vtable pointers - and store them back
// into the panic handler frame
let tmp_ptr = ecx.machine.box_me_up_tmp_ptr.take().unwrap();
let real_ret = ecx.read_immediate(tmp_ptr.into())?;
let payload_data_ptr = real_ret.to_scalar_ptr()?;
let payload_vtable_ptr = real_ret.to_meta()?.expect("Expected fat pointer");


let data_ptr = unwind_data.data_ptr.clone();
let vtable_ptr = unwind_data.vtable_ptr.clone();
let dest = unwind_data.dest.clone();
let ret = unwind_data.ret.clone();
drop(unwind_data);


// Here, we write directly into the frame of the function
// that called '__rust_maybe_catch_panic'.
// (NOT the function that called '__rust_start_panic')

ecx.write_scalar(payload_data_ptr, data_ptr.into())?;
ecx.write_scalar(payload_vtable_ptr, vtable_ptr.into())?;

// We 'return' the value 1 from __rust_maybe_catch_panic,
// since there was a panic
ecx.write_scalar(Scalar::from_int(1, dest.layout.size), dest)?;
ecx.machine.unwinding = false;

ecx.memory_mut().deallocate(tmp_ptr.to_ptr()?, None, MiriMemoryKind::UnwindHelper.into())?;

// We're done - continue execution in the frame of the function
// that called '__rust_maybe_catch_panic,'
//this.goto_block(Some(ret))?;

}
}
ecx.memory().extra.borrow_mut().end_call(extra.call_id);
Ok(StackPopInfo { unwinding: ecx.machine.unwinding })
}
Expand Down

0 comments on commit 6d195bc

Please sign in to comment.