diff --git a/src/eval_context.rs b/src/eval_context.rs index 69469c30e4815f719172cf93cc9429ac2fdf7a13..185f4e1709b2284c5d6016c46f2d915287ad9838 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -66,8 +66,7 @@ pub struct Frame<'tcx> { pub return_to_block: StackPopCleanup, /// The location where the result of the current stack frame should be written to. - /// None if the function is a diverging function - pub return_lvalue: Option>, + pub return_lvalue: Lvalue<'tcx>, /// The list of locals for this stack frame, stored in order as /// `[arguments..., variables..., temporaries...]`. The locals are stored as `Option`s. @@ -272,7 +271,7 @@ pub fn push_stack_frame( instance: ty::Instance<'tcx>, span: codemap::Span, mir: &'tcx mir::Mir<'tcx>, - return_lvalue: Option>, + return_lvalue: Lvalue<'tcx>, return_to_block: StackPopCleanup, ) -> EvalResult<'tcx> { ::log_settings::settings().indentation += 1; @@ -329,7 +328,7 @@ pub(super) fn pop_stack_frame(&mut self) -> EvalResult<'tcx> { ::log_settings::settings().indentation -= 1; let frame = self.stack.pop().expect("tried to pop a stack frame, but there were none"); match frame.return_to_block { - StackPopCleanup::MarkStatic(mutable) => if let Lvalue::Global(id) = frame.return_lvalue.expect("diverging static") { + StackPopCleanup::MarkStatic(mutable) => if let Lvalue::Global(id) = frame.return_lvalue { let global_value = self.globals.get_mut(&id) .expect("global should have been cached (static)"); match global_value.value { diff --git a/src/lvalue.rs b/src/lvalue.rs index b61c18274aeb05adba0c13ecd72194e878d7a838..0205472254ce6fdf8a1a359b7f5e520926b6ff3c 100644 --- a/src/lvalue.rs +++ b/src/lvalue.rs @@ -64,6 +64,14 @@ pub struct Global<'tcx> { } impl<'tcx> Lvalue<'tcx> { + /// Produces an Lvalue that will error if attempted to be read from + pub fn undef() -> Self { + Lvalue::Ptr { + ptr: PrimVal::Undef, + extra: LvalueExtra::None, + } + } + pub fn zst() -> Self { Self::from_ptr(Pointer::zst_ptr()) } @@ -148,7 +156,7 @@ pub(super) fn eval_and_read_lvalue(&mut self, lvalue: &mir::Lvalue<'tcx>) -> Eva pub(super) fn eval_lvalue(&mut self, mir_lvalue: &mir::Lvalue<'tcx>) -> EvalResult<'tcx, Lvalue<'tcx>> { use rustc::mir::Lvalue::*; let lvalue = match *mir_lvalue { - Local(mir::RETURN_POINTER) => self.frame().return_lvalue.expect("diverging function returned"), + Local(mir::RETURN_POINTER) => self.frame().return_lvalue, Local(local) => Lvalue::Local { frame: self.stack.len() - 1, local, field: None }, Static(ref static_) => { diff --git a/src/step.rs b/src/step.rs index a1a9409e2e6a72714b5b02530374514cdde72045..48b9fecd3d39e47cd4e42ab972ff841ed410b8e7 100644 --- a/src/step.rs +++ b/src/step.rs @@ -192,7 +192,7 @@ fn global_item( instance, span, mir, - Some(Lvalue::Global(cid)), + Lvalue::Global(cid), cleanup, ) }); @@ -235,7 +235,7 @@ fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: mir::Loca this.ecx.push_stack_frame(this.instance, constant.span, mir, - Some(Lvalue::Global(cid)), + Lvalue::Global(cid), StackPopCleanup::MarkStatic(false), ) }); diff --git a/src/terminator/drop.rs b/src/terminator/drop.rs index 463d9b3388b53b2916ab0b0e844ef7137592866e..663d05254e5ccd0fee6e4a8485ce4e7b8986e8b6 100644 --- a/src/terminator/drop.rs +++ b/src/terminator/drop.rs @@ -49,7 +49,7 @@ pub(crate) fn drop(&mut self, arg: Value, mut instance: ty::Instance<'tcx>, ty: instance, span, mir, - Some(Lvalue::zst()), + Lvalue::zst(), StackPopCleanup::None, )?; diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index b9182a532e40fe40c5b899ead4a8a0c669fa673c..6ec607295dc72ccc75c45e164e4877b865fc705b 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -30,7 +30,7 @@ pub(super) fn eval_terminator( use rustc::mir::TerminatorKind::*; match terminator.kind { Return => { - self.dump_local(self.frame().return_lvalue.expect("diverging function returned")); + self.dump_local(self.frame().return_lvalue); self.pop_stack_frame()? } @@ -430,8 +430,8 @@ fn eval_fn_call_inner( Err(other) => return Err(other), }; let (return_lvalue, return_to_block) = match destination { - Some((lvalue, block)) => (Some(lvalue), StackPopCleanup::Goto(block)), - None => (None, StackPopCleanup::None), + Some((lvalue, block)) => (lvalue, StackPopCleanup::Goto(block)), + None => (Lvalue::undef(), StackPopCleanup::None), }; self.push_stack_frame( @@ -606,7 +606,7 @@ fn call_c_abi( f_instance, mir.span, mir, - Some(Lvalue::zst()), + Lvalue::zst(), StackPopCleanup::Goto(dest_block), )?;