don't always allocate for the uninit
intrinsic
This commit is contained in:
parent
92f6874ead
commit
a9b984d21e
2 changed files with 27 additions and 15 deletions
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue