make StorageLive kill the current value of the local

This commit is contained in:
Ralf Jung 2017-06-01 17:59:00 -07:00
parent db6ce463fe
commit dd7735b722
2 changed files with 9 additions and 13 deletions

View file

@ -1720,15 +1720,12 @@ impl<'tcx> Frame<'tcx> {
return Ok(());
}
pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx> {
pub fn storage_live(&mut self, local: mir::Local) -> EvalResult<'tcx, Option<Value>> {
trace!("{:?} is now live", local);
if self.locals[local.index() - 1].is_some() {
// The variables comes live now, but was already accessed previously, when it was still dead
return Err(EvalError::DeadLocal);
} else {
self.locals[local.index() - 1] = Some(Value::ByVal(PrimVal::Undef));
}
return Ok(());
let old = self.locals[local.index() - 1];
self.locals[local.index() - 1] = Some(Value::ByVal(PrimVal::Undef)); // StorageLive *always* kills the value that's currently stored
return Ok(old);
}
/// Returns the old value of the local

View file

@ -132,13 +132,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Lvalue::Local{ frame, local, field: None } if self.stack.len() == frame+1 => (frame, local),
_ => return Err(EvalError::Unimplemented("Stroage annotations must refer to locals of the topmost stack frame.".to_owned())) // FIXME maybe this should get its own error type
};
match stmt.kind {
let old_val = match stmt.kind {
StorageLive(_) => self.stack[frame].storage_live(local)?,
_ => {
let old_val = self.stack[frame].storage_dead(local)?;
self.deallocate_local(old_val)?;
}
StorageDead(_) => self.stack[frame].storage_dead(local)?,
_ => bug!("We already checked that we are a storage stmt")
};
self.deallocate_local(old_val)?;
}
// Defined to do nothing. These are added by optimization passes, to avoid changing the