1
Fork 0

don't always allocate for the uninit intrinsic

This commit is contained in:
Oliver Schneider 2016-11-03 13:13:47 +01:00
parent 92f6874ead
commit a9b984d21e
No known key found for this signature in database
GPG key ID: 56D6EEA0FC67AC46
2 changed files with 27 additions and 15 deletions

View file

@ -1555,7 +1555,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
/// convenience function to ensure correct usage of globals and code-sharing with locals /// convenience function to ensure correct usage of globals and code-sharing with locals
pub fn modify_global< pub fn modify_global<
F: FnOnce(&mut Self, Option<Value>) -> EvalResult<'tcx, Value>, F: FnOnce(&mut Self, Option<Value>) -> EvalResult<'tcx, Option<Value>>,
>( >(
&mut self, &mut self,
cid: GlobalId<'tcx>, cid: GlobalId<'tcx>,
@ -1565,14 +1565,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
if !val.mutable { if !val.mutable {
return Err(EvalError::ModifiedConstantMemory); return Err(EvalError::ModifiedConstantMemory);
} }
val.data = Some(f(self, val.data)?); val.data = f(self, val.data)?;
*self.globals.get_mut(&cid).expect("already checked") = val; *self.globals.get_mut(&cid).expect("already checked") = val;
Ok(()) Ok(())
} }
/// convenience function to ensure correct usage of locals and code-sharing with globals /// convenience function to ensure correct usage of locals and code-sharing with globals
pub fn modify_local< pub fn modify_local<
F: FnOnce(&mut Self, Option<Value>) -> EvalResult<'tcx, Value>, F: FnOnce(&mut Self, Option<Value>) -> EvalResult<'tcx, Option<Value>>,
>( >(
&mut self, &mut self,
frame: usize, frame: usize,
@ -1581,7 +1581,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
) -> EvalResult<'tcx, ()> { ) -> EvalResult<'tcx, ()> {
let val = self.stack[frame].get_local(local); let val = self.stack[frame].get_local(local);
let val = f(self, val)?; let val = f(self, val)?;
self.stack[frame].set_local(local, val); // can't use `set_local` here, because that's only meant for going to an initialized value
self.stack[frame].locals[local.index() - 1] = val;
Ok(()) Ok(())
} }
} }

View file

@ -131,21 +131,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
match val { match val {
Some(Value::ByRef(ptr)) => { Some(Value::ByRef(ptr)) => {
this.memory.write_repeat(ptr, 0, size)?; this.memory.write_repeat(ptr, 0, size)?;
Ok(Value::ByRef(ptr)) Ok(Some(Value::ByRef(ptr)))
}, },
None => match this.ty_to_primval_kind(dest_ty) { None => match this.ty_to_primval_kind(dest_ty) {
Ok(kind) => Ok(Value::ByVal(PrimVal::new(0, kind))), Ok(kind) => Ok(Some(Value::ByVal(PrimVal::new(0, kind)))),
Err(_) => { Err(_) => {
let ptr = this.alloc_ptr_with_substs(dest_ty, substs)?; let ptr = this.alloc_ptr_with_substs(dest_ty, substs)?;
this.memory.write_repeat(ptr, 0, size)?; this.memory.write_repeat(ptr, 0, size)?;
Ok(Value::ByRef(ptr)) Ok(Some(Value::ByRef(ptr)))
} }
}, },
Some(Value::ByVal(value)) => Ok(Value::ByVal(PrimVal::new(0, value.kind))), Some(Value::ByVal(value)) => Ok(Some(Value::ByVal(PrimVal::new(0, value.kind)))),
Some(Value::ByValPair(a, b)) => Ok(Value::ByValPair( Some(Value::ByValPair(a, b)) => Ok(Some(Value::ByValPair(
PrimVal::new(0, a.kind), PrimVal::new(0, a.kind),
PrimVal::new(0, b.kind), PrimVal::new(0, b.kind),
)), ))),
} }
}; };
match dest { match dest {
@ -271,12 +271,23 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
} }
"uninit" => { "uninit" => {
// FIXME(solson): Attempt writing a None over the destination when it's an
// Lvalue::Local (that is not ByRef). Otherwise do the mark_definedness as usual.
let dest = self.force_allocation(dest)?.to_ptr();
let size = dest_layout.size(&self.tcx.data_layout).bytes() as usize; let size = dest_layout.size(&self.tcx.data_layout).bytes() as usize;
self.memory.mark_definedness(dest, size, false)?; let uninit = |this: &mut Self, val: Option<Value>| {
match val {
Some(Value::ByRef(ptr)) => {
this.memory.mark_definedness(ptr, size, false)?;
Ok(Some(Value::ByRef(ptr)))
},
None => Ok(None),
Some(_) => Ok(None),
}
};
match dest {
Lvalue::Local { frame, local } => self.modify_local(frame, local, uninit)?,
Lvalue::Ptr { ptr, extra: LvalueExtra::None } => self.memory.mark_definedness(ptr, size, false)?,
Lvalue::Ptr { .. } => bug!("uninit intrinsic tried to write to fat ptr target"),
Lvalue::Global(cid) => self.modify_global(cid, uninit)?,
}
} }
name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))), name => return Err(EvalError::Unimplemented(format!("unimplemented intrinsic: {}", name))),