diff --git a/src/interpreter/terminator/intrinsics.rs b/src/interpreter/terminator/intrinsics.rs index 48098e4f497..2b10f825038 100644 --- a/src/interpreter/terminator/intrinsics.rs +++ b/src/interpreter/terminator/intrinsics.rs @@ -6,7 +6,7 @@ use rustc::ty::{self, Ty}; use error::{EvalError, EvalResult}; use interpreter::value::Value; -use interpreter::{EvalContext, Lvalue}; +use interpreter::{EvalContext, Lvalue, LvalueExtra}; use primval::{self, PrimVal, PrimValKind}; impl<'a, 'tcx> EvalContext<'a, 'tcx> { @@ -126,11 +126,54 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "forget" => {} "init" => { - // FIXME(solson) - let dest = self.force_allocation(dest)?.to_ptr(); - let size = dest_layout.size(&self.tcx.data_layout).bytes() as usize; - self.memory.write_repeat(dest, 0, size)?; + match dest { + Lvalue::Local { frame, local } => { + match self.stack[frame].get_local(local) { + Some(Value::ByRef(ptr)) => self.memory.write_repeat(ptr, 0, size)?, + None => match self.ty_to_primval_kind(dest_ty) { + Ok(kind) => self.stack[frame].set_local(local, Value::ByVal(PrimVal::new(0, kind))), + Err(_) => { + let ptr = self.alloc_ptr_with_substs(dest_ty, substs)?; + self.memory.write_repeat(ptr, 0, size)?; + self.stack[frame].set_local(local, Value::ByRef(ptr)); + } + }, + Some(Value::ByVal(val)) => self.stack[frame].set_local(local, Value::ByVal(PrimVal::new(0, val.kind))), + Some(Value::ByValPair(a, b)) => self.stack[frame].set_local(local, Value::ByValPair( + PrimVal::new(0, a.kind), + PrimVal::new(0, b.kind), + )), + } + } + Lvalue::Ptr { ptr, extra: LvalueExtra::None } => self.memory.write_repeat(ptr, 0, size)?, + Lvalue::Ptr { .. } => bug!("init intrinsic tried to write to fat ptr target"), + Lvalue::Global(cid) => { + let global_val = *self.globals.get(&cid).expect("global not cached"); + if !global_val.mutable { + return Err(EvalError::ModifiedConstantMemory); + } + match global_val.data { + Some(Value::ByRef(ptr)) => self.memory.write_repeat(ptr, 0, size)?, + None => match self.ty_to_primval_kind(dest_ty) { + Ok(kind) => self.globals + .get_mut(&cid) + .expect("already checked") + .data = Some(Value::ByVal(PrimVal::new(0, kind))), + Err(_) => { + let ptr = self.alloc_ptr_with_substs(dest_ty, substs)?; + self.memory.write_repeat(ptr, 0, size)?; + self.globals.get_mut(&cid).expect("already checked").data = Some(Value::ByRef(ptr)); + }, + }, + Some(Value::ByVal(val)) => self.globals.get_mut(&cid).expect("already checked").data = Some(Value::ByVal(PrimVal::new(0, val.kind))), + Some(Value::ByValPair(a, b)) => self.globals.get_mut(&cid).expect("already checked").data = Some(Value::ByValPair( + PrimVal::new(0, a.kind), + PrimVal::new(0, b.kind), + )), + } + } + } } "min_align_of" => {