Only check pointers when dereferencing
Before we also checked whether pointers had alloc_ids when we created rvalue references
This commit is contained in:
parent
8ff5d59efe
commit
823b952ef2
@ -351,7 +351,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let global_value = self.globals.get_mut(&id)
|
||||
.expect("global should have been cached (static)");
|
||||
match global_value.value {
|
||||
Value::ByRef(ptr) => self.memory.mark_static_initalized(ptr.alloc_id, mutable)?,
|
||||
// FIXME: to_ptr()? might be too extreme here, static zsts might reach this under certain conditions
|
||||
Value::ByRef(ptr) => self.memory.mark_static_initalized(ptr.to_ptr()?.alloc_id, mutable)?,
|
||||
Value::ByVal(val) => if let PrimVal::Ptr(ptr) = val {
|
||||
self.memory.mark_inner_allocation(ptr.alloc_id, mutable)?;
|
||||
},
|
||||
@ -409,6 +410,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
pub fn deallocate_local(&mut self, local: Option<Value>) -> EvalResult<'tcx> {
|
||||
if let Some(Value::ByRef(ptr)) = local {
|
||||
trace!("deallocating local");
|
||||
let ptr = ptr.to_ptr()?;
|
||||
self.memory.dump_alloc(ptr.alloc_id);
|
||||
match self.memory.deallocate(ptr) {
|
||||
// We could alternatively check whether the alloc_id is static before calling
|
||||
@ -693,26 +695,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
// Check alignment and non-NULLness.
|
||||
let (_, align) = self.size_and_align_of_dst(ty, val)?;
|
||||
match ptr {
|
||||
PrimVal::Ptr(ptr) => {
|
||||
self.memory.check_align(ptr, align, 0)?;
|
||||
}
|
||||
PrimVal::Bytes(bytes) => {
|
||||
let v = ((bytes as u128) % (1 << self.memory.pointer_size())) as u64;
|
||||
if v == 0 {
|
||||
return Err(EvalError::InvalidNullPointerUsage);
|
||||
}
|
||||
if v % align != 0 {
|
||||
return Err(EvalError::AlignmentCheckFailed {
|
||||
has: v % align,
|
||||
required: align,
|
||||
});
|
||||
}
|
||||
}
|
||||
PrimVal::Undef => {
|
||||
return Err(EvalError::ReadUndefBytes);
|
||||
}
|
||||
}
|
||||
self.memory.check_align(ptr, align, 0)?;
|
||||
|
||||
self.write_value(val, dest, dest_ty)?;
|
||||
}
|
||||
@ -1036,14 +1019,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
match self.stack[frame].locals[local.index() - 1] {
|
||||
None => return Err(EvalError::DeadLocal),
|
||||
Some(Value::ByRef(ptr)) => {
|
||||
Lvalue::from_ptr(ptr)
|
||||
Lvalue::from_primval_ptr(ptr)
|
||||
},
|
||||
Some(val) => {
|
||||
let ty = self.stack[frame].mir.local_decls[local].ty;
|
||||
let ty = self.monomorphize(ty, self.stack[frame].instance.substs);
|
||||
let substs = self.stack[frame].instance.substs;
|
||||
let ptr = self.alloc_ptr_with_substs(ty, substs)?;
|
||||
self.stack[frame].locals[local.index() - 1] = Some(Value::ByRef(ptr)); // it stays live
|
||||
self.stack[frame].locals[local.index() - 1] = Some(Value::ByRef(PrimVal::Ptr(ptr))); // it stays live
|
||||
self.write_value_to_ptr(val, PrimVal::Ptr(ptr), ty)?;
|
||||
Lvalue::from_ptr(ptr)
|
||||
}
|
||||
@ -1053,7 +1036,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Lvalue::Global(cid) => {
|
||||
let global_val = *self.globals.get(&cid).expect("global not cached");
|
||||
match global_val.value {
|
||||
Value::ByRef(ptr) => Lvalue::from_ptr(ptr),
|
||||
Value::ByRef(ptr) => Lvalue::from_primval_ptr(ptr),
|
||||
_ => {
|
||||
let ptr = self.alloc_ptr_with_substs(global_val.ty, cid.instance.substs)?;
|
||||
self.memory.mark_static(ptr.alloc_id);
|
||||
@ -1064,7 +1047,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
let lval = self.globals.get_mut(&cid).expect("already checked");
|
||||
*lval = Global {
|
||||
value: Value::ByRef(ptr),
|
||||
value: Value::ByRef(PrimVal::Ptr(ptr)),
|
||||
.. global_val
|
||||
};
|
||||
Lvalue::from_ptr(ptr)
|
||||
@ -1160,7 +1143,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
//
|
||||
// Thus, it would be an error to replace the `ByRef` with a `ByVal`, unless we
|
||||
// knew for certain that there were no outstanding pointers to this allocation.
|
||||
self.write_value_to_ptr(src_val, PrimVal::Ptr(dest_ptr), dest_ty)?;
|
||||
self.write_value_to_ptr(src_val, dest_ptr, dest_ty)?;
|
||||
|
||||
} else if let Value::ByRef(src_ptr) = src_val {
|
||||
// If the value is not `ByRef`, then we know there are no pointers to it
|
||||
@ -1178,8 +1161,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
write_dest(self, src_val)?;
|
||||
} else {
|
||||
let dest_ptr = self.alloc_ptr(dest_ty)?;
|
||||
self.copy(PrimVal::Ptr(src_ptr), PrimVal::Ptr(dest_ptr), dest_ty)?;
|
||||
write_dest(self, Value::ByRef(dest_ptr))?;
|
||||
self.copy(src_ptr, PrimVal::Ptr(dest_ptr), dest_ty)?;
|
||||
write_dest(self, Value::ByRef(PrimVal::Ptr(dest_ptr)))?;
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -1197,7 +1180,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
dest_ty: Ty<'tcx>,
|
||||
) -> EvalResult<'tcx> {
|
||||
match value {
|
||||
Value::ByRef(ptr) => self.copy(PrimVal::Ptr(ptr), dest, dest_ty),
|
||||
Value::ByRef(ptr) => self.copy(ptr, dest, dest_ty),
|
||||
Value::ByVal(primval) => {
|
||||
let size = self.type_size(dest_ty)?.expect("dest type must be sized");
|
||||
self.memory.write_primval(dest, primval, size)
|
||||
@ -1327,7 +1310,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
|
||||
pub(super) fn read_value(&mut self, ptr: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> {
|
||||
if let Some(val) = self.try_read_value(ptr, ty)? {
|
||||
Ok(val)
|
||||
} else {
|
||||
@ -1352,13 +1335,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn try_read_value(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
|
||||
fn try_read_value(&mut self, ptr: PrimVal, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> {
|
||||
use syntax::ast::FloatTy;
|
||||
|
||||
let val = match ty.sty {
|
||||
ty::TyBool => PrimVal::from_bool(self.memory.read_bool(ptr)?),
|
||||
ty::TyBool => PrimVal::from_bool(self.memory.read_bool(ptr.to_ptr()?)?),
|
||||
ty::TyChar => {
|
||||
let c = self.memory.read_uint(ptr, 4)? as u32;
|
||||
let c = self.memory.read_uint(ptr.to_ptr()?, 4)? as u32;
|
||||
match ::std::char::from_u32(c) {
|
||||
Some(ch) => PrimVal::from_char(ch),
|
||||
None => return Err(EvalError::InvalidChar(c as u128)),
|
||||
@ -1377,8 +1360,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
};
|
||||
// if we transmute a ptr to an isize, reading it back into a primval shouldn't panic
|
||||
// Due to read_ptr ignoring the sign, we need to jump around some hoops
|
||||
match self.memory.read_int(ptr, size) {
|
||||
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr)?,
|
||||
match self.memory.read_int(ptr.to_ptr()?, size) {
|
||||
Err(EvalError::ReadPointerAsBytes) if size == self.memory.pointer_size() => self.memory.read_ptr(ptr.to_ptr()?)?,
|
||||
other => PrimVal::from_i128(other?),
|
||||
}
|
||||
}
|
||||
@ -1395,30 +1378,30 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
};
|
||||
if size == self.memory.pointer_size() {
|
||||
// if we transmute a ptr to an usize, reading it back into a primval shouldn't panic
|
||||
self.memory.read_ptr(ptr)?
|
||||
self.memory.read_ptr(ptr.to_ptr()?)?
|
||||
} else {
|
||||
PrimVal::from_u128(self.memory.read_uint(ptr, size)?)
|
||||
PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?)
|
||||
}
|
||||
}
|
||||
|
||||
ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr)?),
|
||||
ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr)?),
|
||||
ty::TyFloat(FloatTy::F32) => PrimVal::from_f32(self.memory.read_f32(ptr.to_ptr()?)?),
|
||||
ty::TyFloat(FloatTy::F64) => PrimVal::from_f64(self.memory.read_f64(ptr.to_ptr()?)?),
|
||||
|
||||
ty::TyFnPtr(_) => self.memory.read_ptr(ptr)?,
|
||||
ty::TyFnPtr(_) => self.memory.read_ptr(ptr.to_ptr()?)?,
|
||||
ty::TyRef(_, ref tam) |
|
||||
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr, tam.ty).map(Some),
|
||||
ty::TyRawPtr(ref tam) => return self.read_ptr(ptr.to_ptr()?, tam.ty).map(Some),
|
||||
|
||||
ty::TyAdt(def, _) => {
|
||||
if def.is_box() {
|
||||
return self.read_ptr(ptr, ty.boxed_ty()).map(Some);
|
||||
return self.read_ptr(ptr.to_ptr()?, ty.boxed_ty()).map(Some);
|
||||
}
|
||||
use rustc::ty::layout::Layout::*;
|
||||
if let CEnum { discr, signed, .. } = *self.type_layout(ty)? {
|
||||
let size = discr.size().bytes();
|
||||
if signed {
|
||||
PrimVal::from_i128(self.memory.read_int(ptr, size)?)
|
||||
PrimVal::from_i128(self.memory.read_int(ptr.to_ptr()?, size)?)
|
||||
} else {
|
||||
PrimVal::from_u128(self.memory.read_uint(ptr, size)?)
|
||||
PrimVal::from_u128(self.memory.read_uint(ptr.to_ptr()?, size)?)
|
||||
}
|
||||
} else {
|
||||
return Ok(None);
|
||||
@ -1537,7 +1520,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let src_f_ptr = src_ptr.offset(src_field_offset, self.memory.layout)?;
|
||||
let dst_f_ptr = dest.offset(dst_field_offset, self.memory.layout)?;
|
||||
if src_fty == dst_fty {
|
||||
self.copy(PrimVal::Ptr(src_f_ptr), PrimVal::Ptr(dst_f_ptr), src_fty)?;
|
||||
self.copy(src_f_ptr, PrimVal::Ptr(dst_f_ptr), src_fty)?;
|
||||
} else {
|
||||
self.unsize_into(Value::ByRef(src_f_ptr), src_fty, Lvalue::from_ptr(dst_f_ptr), dst_fty)?;
|
||||
}
|
||||
@ -1566,10 +1549,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Err(err) => {
|
||||
panic!("Failed to access local: {:?}", err);
|
||||
}
|
||||
Ok(Value::ByRef(ptr)) => {
|
||||
Ok(Value::ByRef(PrimVal::Ptr(ptr))) => {
|
||||
write!(msg, " by ref:").unwrap();
|
||||
allocs.push(ptr.alloc_id);
|
||||
}
|
||||
Ok(Value::ByRef(ptr)) => {
|
||||
write!(msg, " integral by ref: {:?}", ptr).unwrap();
|
||||
}
|
||||
Ok(Value::ByVal(val)) => {
|
||||
write!(msg, " {:?}", val).unwrap();
|
||||
if let PrimVal::Ptr(ptr) = val { allocs.push(ptr.alloc_id); }
|
||||
|
@ -67,11 +67,11 @@ impl<'tcx> Lvalue<'tcx> {
|
||||
Self::from_primval_ptr(PrimVal::Undef)
|
||||
}
|
||||
|
||||
fn from_primval_ptr(ptr: PrimVal) -> Self {
|
||||
pub(crate) fn from_primval_ptr(ptr: PrimVal) -> Self {
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::None }
|
||||
}
|
||||
|
||||
pub fn from_ptr(ptr: Pointer) -> Self {
|
||||
pub(crate) fn from_ptr(ptr: Pointer) -> Self {
|
||||
Self::from_primval_ptr(PrimVal::Ptr(ptr))
|
||||
}
|
||||
|
||||
@ -192,7 +192,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
match lvalue {
|
||||
Lvalue::Ptr { ptr, extra } => {
|
||||
assert_eq!(extra, LvalueExtra::None);
|
||||
Ok(Value::ByRef(ptr.to_ptr()?))
|
||||
Ok(Value::ByRef(ptr))
|
||||
}
|
||||
Lvalue::Local { frame, local } => {
|
||||
self.stack[frame].get_local(local)
|
||||
|
@ -189,7 +189,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
}
|
||||
|
||||
let ptr = self.allocate(bytes.len() as u64, 1)?;
|
||||
self.write_bytes(ptr, bytes)?;
|
||||
self.write_bytes(PrimVal::Ptr(ptr), bytes)?;
|
||||
self.mark_static_initalized(ptr.alloc_id, false)?;
|
||||
self.literal_alloc_cache.insert(bytes.to_vec(), ptr.alloc_id);
|
||||
Ok(ptr)
|
||||
@ -288,39 +288,52 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
self.layout.endian
|
||||
}
|
||||
|
||||
pub fn check_align(&self, ptr: Pointer, align: u64, len: u64) -> EvalResult<'tcx> {
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
// check whether the memory was marked as packed
|
||||
// we select all elements that have the correct alloc_id and are within
|
||||
// the range given by the offset into the allocation and the length
|
||||
let start = Entry {
|
||||
alloc_id: ptr.alloc_id,
|
||||
packed_start: 0,
|
||||
packed_end: ptr.offset + len,
|
||||
pub fn check_align(&self, ptr: PrimVal, align: u64, len: u64) -> EvalResult<'tcx> {
|
||||
let offset = match ptr {
|
||||
PrimVal::Ptr(ptr) => {
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
// check whether the memory was marked as packed
|
||||
// we select all elements that have the correct alloc_id and are within
|
||||
// the range given by the offset into the allocation and the length
|
||||
let start = Entry {
|
||||
alloc_id: ptr.alloc_id,
|
||||
packed_start: 0,
|
||||
packed_end: ptr.offset + len,
|
||||
};
|
||||
let end = Entry {
|
||||
alloc_id: ptr.alloc_id,
|
||||
packed_start: ptr.offset + len,
|
||||
packed_end: 0,
|
||||
};
|
||||
for &Entry { packed_start, packed_end, .. } in self.packed.range(start..end) {
|
||||
// if the region we are checking is covered by a region in `packed`
|
||||
// ignore the actual alignment
|
||||
if packed_start <= ptr.offset && (ptr.offset + len) <= packed_end {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
if alloc.align < align {
|
||||
return Err(EvalError::AlignmentCheckFailed {
|
||||
has: alloc.align,
|
||||
required: align,
|
||||
});
|
||||
}
|
||||
ptr.offset
|
||||
},
|
||||
PrimVal::Bytes(bytes) => {
|
||||
let v = ((bytes as u128) % (1 << self.pointer_size())) as u64;
|
||||
if v == 0 {
|
||||
return Err(EvalError::InvalidNullPointerUsage);
|
||||
}
|
||||
v
|
||||
},
|
||||
PrimVal::Undef => return Err(EvalError::ReadUndefBytes),
|
||||
};
|
||||
let end = Entry {
|
||||
alloc_id: ptr.alloc_id,
|
||||
packed_start: ptr.offset + len,
|
||||
packed_end: 0,
|
||||
};
|
||||
for &Entry { packed_start, packed_end, .. } in self.packed.range(start..end) {
|
||||
// if the region we are checking is covered by a region in `packed`
|
||||
// ignore the actual alignment
|
||||
if packed_start <= ptr.offset && (ptr.offset + len) <= packed_end {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
if alloc.align < align {
|
||||
return Err(EvalError::AlignmentCheckFailed {
|
||||
has: alloc.align,
|
||||
required: align,
|
||||
});
|
||||
}
|
||||
if ptr.offset % align == 0 {
|
||||
if offset % align == 0 {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(EvalError::AlignmentCheckFailed {
|
||||
has: ptr.offset % align,
|
||||
has: offset % align,
|
||||
required: align,
|
||||
})
|
||||
}
|
||||
@ -572,7 +585,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
if size == 0 {
|
||||
return Ok(&[]);
|
||||
}
|
||||
self.check_align(ptr, align, size)?;
|
||||
self.check_align(PrimVal::Ptr(ptr), align, size)?;
|
||||
self.check_bounds(ptr.offset(size, self.layout)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
let alloc = self.get(ptr.alloc_id)?;
|
||||
assert_eq!(ptr.offset as usize as u64, ptr.offset);
|
||||
@ -585,7 +598,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
if size == 0 {
|
||||
return Ok(&mut []);
|
||||
}
|
||||
self.check_align(ptr, align, size)?;
|
||||
self.check_align(PrimVal::Ptr(ptr), align, size)?;
|
||||
self.check_bounds(ptr.offset(size, self.layout)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
|
||||
let alloc = self.get_mut(ptr.alloc_id)?;
|
||||
assert_eq!(ptr.offset as usize as u64, ptr.offset);
|
||||
@ -710,20 +723,20 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
|
||||
self.get_bytes(ptr.to_ptr()?, size, 1)
|
||||
}
|
||||
|
||||
pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> {
|
||||
pub fn write_bytes(&mut self, ptr: PrimVal, src: &[u8]) -> EvalResult<'tcx> {
|
||||
if src.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let bytes = self.get_bytes_mut(ptr, src.len() as u64, 1)?;
|
||||
let bytes = self.get_bytes_mut(ptr.to_ptr()?, src.len() as u64, 1)?;
|
||||
bytes.clone_from_slice(src);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> {
|
||||
pub fn write_repeat(&mut self, ptr: PrimVal, val: u8, count: u64) -> EvalResult<'tcx> {
|
||||
if count == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let bytes = self.get_bytes_mut(ptr, count, 1)?;
|
||||
let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, 1)?;
|
||||
for b in bytes { *b = val; }
|
||||
Ok(())
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
"atomic_load_acq" |
|
||||
"volatile_load" => {
|
||||
let ty = substs.type_at(0);
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
self.write_value(Value::ByRef(ptr), dest, ty)?;
|
||||
}
|
||||
|
||||
@ -79,7 +79,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
|
||||
_ if intrinsic_name.starts_with("atomic_xchg") => {
|
||||
let ty = substs.type_at(0);
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let change = self.value_to_primval(arg_vals[1], ty)?;
|
||||
let old = self.read_value(ptr, ty)?;
|
||||
let old = match old {
|
||||
@ -88,12 +88,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Value::ByValPair(..) => bug!("atomic_xchg doesn't work with nonprimitives"),
|
||||
};
|
||||
self.write_primval(dest, old, ty)?;
|
||||
self.write_primval(Lvalue::from_ptr(ptr), change, ty)?;
|
||||
self.write_primval(Lvalue::from_primval_ptr(ptr), change, ty)?;
|
||||
}
|
||||
|
||||
_ if intrinsic_name.starts_with("atomic_cxchg") => {
|
||||
let ty = substs.type_at(0);
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let expect_old = self.value_to_primval(arg_vals[1], ty)?;
|
||||
let change = self.value_to_primval(arg_vals[2], ty)?;
|
||||
let old = self.read_value(ptr, ty)?;
|
||||
@ -105,7 +105,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let (val, _) = self.binary_op(mir::BinOp::Eq, old, ty, expect_old, ty)?;
|
||||
let dest = self.force_allocation(dest)?.to_ptr()?;
|
||||
self.write_pair_to_ptr(old, val, dest, dest_ty)?;
|
||||
self.write_primval(Lvalue::from_ptr(ptr), change, ty)?;
|
||||
self.write_primval(Lvalue::from_primval_ptr(ptr), change, ty)?;
|
||||
}
|
||||
|
||||
"atomic_or" | "atomic_or_acq" | "atomic_or_rel" | "atomic_or_acqrel" | "atomic_or_relaxed" |
|
||||
@ -114,7 +114,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
"atomic_xadd" | "atomic_xadd_acq" | "atomic_xadd_rel" | "atomic_xadd_acqrel" | "atomic_xadd_relaxed" |
|
||||
"atomic_xsub" | "atomic_xsub_acq" | "atomic_xsub_rel" | "atomic_xsub_acqrel" | "atomic_xsub_relaxed" => {
|
||||
let ty = substs.type_at(0);
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?.to_ptr()?;
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let change = self.value_to_primval(arg_vals[1], ty)?;
|
||||
let old = self.read_value(ptr, ty)?;
|
||||
let old = match old {
|
||||
@ -133,7 +133,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
};
|
||||
// FIXME: what do atomics do on overflow?
|
||||
let (val, _) = self.binary_op(op, old, ty, change, ty)?;
|
||||
self.write_primval(Lvalue::from_ptr(ptr), val, ty)?;
|
||||
self.write_primval(Lvalue::from_primval_ptr(ptr), val, ty)?;
|
||||
},
|
||||
|
||||
"breakpoint" => unimplemented!(), // halt miri
|
||||
@ -258,8 +258,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
Ok(_) => Value::ByVal(PrimVal::Bytes(0)),
|
||||
Err(_) => {
|
||||
let ptr = this.alloc_ptr_with_substs(dest_ty, substs)?;
|
||||
this.memory.write_repeat(ptr, 0, size)?;
|
||||
Value::ByRef(ptr)
|
||||
this.memory.write_repeat(PrimVal::Ptr(ptr), 0, size)?;
|
||||
Value::ByRef(PrimVal::Ptr(ptr))
|
||||
}
|
||||
},
|
||||
Value::ByVal(_) => Value::ByVal(PrimVal::Bytes(0)),
|
||||
@ -270,7 +270,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
};
|
||||
match dest {
|
||||
Lvalue::Local { frame, local } => self.modify_local(frame, local, init)?,
|
||||
Lvalue::Ptr { ptr, extra: LvalueExtra::None } => self.memory.write_repeat(ptr.to_ptr()?, 0, size)?,
|
||||
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) => self.modify_global(cid, init)?,
|
||||
}
|
||||
@ -412,7 +412,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let uninit = |this: &mut Self, val: Value| {
|
||||
match val {
|
||||
Value::ByRef(ptr) => {
|
||||
this.memory.mark_definedness(PrimVal::Ptr(ptr), size, false)?;
|
||||
this.memory.mark_definedness(ptr, size, false)?;
|
||||
Ok(Value::ByRef(ptr))
|
||||
},
|
||||
_ => Ok(Value::ByVal(PrimVal::Undef)),
|
||||
@ -436,7 +436,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
let ptr = arg_vals[0].read_ptr(&self.memory)?;
|
||||
let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?;
|
||||
if count > 0 {
|
||||
let ptr = ptr.to_ptr()?;
|
||||
self.memory.check_align(ptr, ty_align, size * count)?;
|
||||
self.memory.write_repeat(ptr, val_byte, size * count)?;
|
||||
}
|
||||
|
@ -632,7 +632,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
return Err(EvalError::HeapAllocNonPowerOfTwoAlignment(align));
|
||||
}
|
||||
let ptr = self.memory.allocate(size, align)?;
|
||||
self.memory.write_repeat(ptr, 0, size)?;
|
||||
self.memory.write_repeat(PrimVal::Ptr(ptr), 0, size)?;
|
||||
self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?;
|
||||
}
|
||||
|
||||
@ -792,8 +792,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
|
||||
if let Some((name, value)) = new {
|
||||
// +1 for the null terminator
|
||||
let value_copy = self.memory.allocate((value.len() + 1) as u64, 1)?;
|
||||
self.memory.write_bytes(value_copy, &value)?;
|
||||
self.memory.write_bytes(value_copy.offset(value.len() as u64, self.memory.layout)?, &[0])?;
|
||||
self.memory.write_bytes(PrimVal::Ptr(value_copy), &value)?;
|
||||
self.memory.write_bytes(PrimVal::Ptr(value_copy.offset(value.len() as u64, self.memory.layout)?), &[0])?;
|
||||
if let Some(var) = self.env_vars.insert(name.to_owned(), value_copy) {
|
||||
self.memory.deallocate(var)?;
|
||||
}
|
||||
|
12
src/value.rs
12
src/value.rs
@ -33,7 +33,7 @@ pub(super) fn f64_to_bytes(f: f64) -> u128 {
|
||||
/// operations and fat pointers. This idea was taken from rustc's trans.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum Value {
|
||||
ByRef(Pointer),
|
||||
ByRef(PrimVal),
|
||||
ByVal(PrimVal),
|
||||
ByValPair(PrimVal, PrimVal),
|
||||
}
|
||||
@ -72,7 +72,7 @@ impl<'a, 'tcx: 'a> Value {
|
||||
pub(super) fn read_ptr(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, PrimVal> {
|
||||
use self::Value::*;
|
||||
match *self {
|
||||
ByRef(ptr) => mem.read_ptr(ptr),
|
||||
ByRef(ptr) => mem.read_ptr(ptr.to_ptr()?),
|
||||
ByVal(ptr) | ByValPair(ptr, _) => Ok(ptr),
|
||||
}
|
||||
}
|
||||
@ -84,8 +84,8 @@ impl<'a, 'tcx: 'a> Value {
|
||||
use self::Value::*;
|
||||
match *self {
|
||||
ByRef(ref_ptr) => {
|
||||
let ptr = mem.read_ptr(ref_ptr)?;
|
||||
let vtable = mem.read_ptr(ref_ptr.offset(mem.pointer_size(), mem.layout)?)?;
|
||||
let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
|
||||
let vtable = mem.read_ptr(ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?)?;
|
||||
Ok((ptr, vtable.to_ptr()?))
|
||||
}
|
||||
|
||||
@ -99,8 +99,8 @@ impl<'a, 'tcx: 'a> Value {
|
||||
use self::Value::*;
|
||||
match *self {
|
||||
ByRef(ref_ptr) => {
|
||||
let ptr = mem.read_ptr(ref_ptr)?;
|
||||
let len = mem.read_usize(ref_ptr.offset(mem.pointer_size(), mem.layout)?)?;
|
||||
let ptr = mem.read_ptr(ref_ptr.to_ptr()?)?;
|
||||
let len = mem.read_usize(ref_ptr.offset(mem.pointer_size(), mem.layout)?.to_ptr()?)?;
|
||||
Ok((ptr, len))
|
||||
},
|
||||
ByValPair(ptr, val) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user