diff options
| author | Ralf Jung <post@ralfj.de> | 2017-07-27 09:14:04 -0700 |
|---|---|---|
| committer | Ralf Jung <post@ralfj.de> | 2017-07-27 09:14:04 -0700 |
| commit | 14c8e834b99ca3d422828b44ed0b2d4a76335be6 (patch) | |
| tree | d3f3f31a6fd0a25727e2db69bb52c2c685df5298 | |
| parent | 4672cb7bde348a3096bf1e6125d3cff98bf52b4d (diff) | |
| download | rust-14c8e834b99ca3d422828b44ed0b2d4a76335be6.tar.gz rust-14c8e834b99ca3d422828b44ed0b2d4a76335be6.zip | |
use Cell for memory's aligned flag to avoid infecting interfaces with 'fake' mutability
| -rw-r--r-- | src/librustc_mir/interpret/eval_context.rs | 20 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/lvalue.rs | 8 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/memory.rs | 52 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/step.rs | 2 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/terminator/intrinsic.rs | 30 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/terminator/mod.rs | 44 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/validation.rs | 4 | ||||
| -rw-r--r-- | src/librustc_mir/interpret/value.rs | 8 |
8 files changed, 91 insertions, 77 deletions
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 5913ff168fc..c1ddfb9ffea 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -1161,7 +1161,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Lvalue::Ptr { ptr, extra, aligned } => { assert_eq!(extra, LvalueExtra::None); - self.write_maybe_aligned(aligned, + self.write_maybe_aligned_mut(aligned, |ectx| ectx.write_value_to_ptr(src_val, ptr, dest_ty)) } @@ -1193,7 +1193,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_maybe_aligned(aligned, + self.write_maybe_aligned_mut(aligned, |ectx| ectx.write_value_to_ptr(src_val, dest_ptr, dest_ty))?; } else if let Value::ByRef(src_ptr, aligned) = src_val { @@ -1208,7 +1208,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // It is a valid optimization to attempt reading a primitive value out of the // source and write that into the destination without making an allocation, so // we do so here. - self.read_maybe_aligned(aligned, |ectx| { + self.read_maybe_aligned_mut(aligned, |ectx| { if let Ok(Some(src_val)) = ectx.try_read_value(src_ptr, dest_ty) { write_dest(ectx, src_val)?; } else { @@ -1235,7 +1235,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ) -> EvalResult<'tcx> { match value { Value::ByRef(ptr, aligned) => { - self.read_maybe_aligned(aligned, |ectx| ectx.copy(ptr, dest, dest_ty)) + self.read_maybe_aligned_mut(aligned, |ectx| ectx.copy(ptr, dest, dest_ty)) }, Value::ByVal(primval) => { let size = self.type_size(dest_ty)?.expect("dest type must be sized"); @@ -1270,9 +1270,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let field_1_size = self.type_size(field_1_ty.0)?.expect("pair element type must be sized"); let field_0_ptr = ptr.offset(field_0.bytes(), &self)?.into(); let field_1_ptr = ptr.offset(field_1.bytes(), &self)?.into(); - self.write_maybe_aligned(!packed, + self.write_maybe_aligned_mut(!packed, |ectx| ectx.memory.write_primval(field_0_ptr, a, field_0_size))?; - self.write_maybe_aligned(!packed, + self.write_maybe_aligned_mut(!packed, |ectx| ectx.memory.write_primval(field_1_ptr, b, field_1_size))?; Ok(()) } @@ -1376,7 +1376,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(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Value> { if let Some(val) = self.try_read_value(ptr, ty)? { Ok(val) } else { @@ -1400,7 +1400,7 @@ 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(&self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, Option<Value>> { use syntax::ast::FloatTy; let val = match ty.sty { @@ -1512,7 +1512,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { match (&src_pointee_ty.sty, &dest_pointee_ty.sty) { (&ty::TyArray(_, length), &ty::TySlice(_)) => { - let ptr = src.into_ptr(&mut self.memory)?; + let ptr = src.into_ptr(&self.memory)?; // u64 cast is from usize to u64, which is always good self.write_value(ptr.to_value_with_len(length as u64), dest, dest_ty) } @@ -1526,7 +1526,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let trait_ref = data.principal().unwrap().with_self_ty(self.tcx, src_pointee_ty); let trait_ref = self.tcx.erase_regions(&trait_ref); let vtable = self.get_vtable(src_pointee_ty, trait_ref)?; - let ptr = src.into_ptr(&mut self.memory)?; + let ptr = src.into_ptr(&self.memory)?; self.write_value(ptr.to_value_with_vtable(vtable), dest, dest_ty) }, diff --git a/src/librustc_mir/interpret/lvalue.rs b/src/librustc_mir/interpret/lvalue.rs index da357a6d1e7..4d4db267ecf 100644 --- a/src/librustc_mir/interpret/lvalue.rs +++ b/src/librustc_mir/interpret/lvalue.rs @@ -351,17 +351,17 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(Lvalue::Ptr { ptr, extra, aligned: aligned && !packed }) } - pub(super) fn val_to_lvalue(&mut self, val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Lvalue<'tcx>> { + pub(super) fn val_to_lvalue(&self, val: Value, ty: Ty<'tcx>) -> EvalResult<'tcx, Lvalue<'tcx>> { Ok(match self.tcx.struct_tail(ty).sty { ty::TyDynamic(..) => { - let (ptr, vtable) = val.into_ptr_vtable_pair(&mut self.memory)?; + let (ptr, vtable) = val.into_ptr_vtable_pair(&self.memory)?; Lvalue::Ptr { ptr, extra: LvalueExtra::Vtable(vtable), aligned: true } }, ty::TyStr | ty::TySlice(_) => { - let (ptr, len) = val.into_slice(&mut self.memory)?; + let (ptr, len) = val.into_slice(&self.memory)?; Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len), aligned: true } }, - _ => Lvalue::Ptr { ptr: val.into_ptr(&mut self.memory)?, extra: LvalueExtra::None, aligned: true }, + _ => Lvalue::Ptr { ptr: val.into_ptr(&self.memory)?, extra: LvalueExtra::None, aligned: true }, }) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 591f5dc7fe8..2226744c6ab 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -1,6 +1,7 @@ use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian}; use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque}; use std::{fmt, iter, ptr, mem, io, ops}; +use std::cell::Cell; use rustc::ty; use rustc::ty::layout::{self, TargetDataLayout, HasDataLayout}; @@ -266,8 +267,8 @@ pub struct Memory<'a, 'tcx> { /// To avoid having to pass flags to every single memory access, we have some global state saying whether /// alignment checking is currently enforced for read and/or write accesses. - reads_are_aligned: bool, - writes_are_aligned: bool, + reads_are_aligned: Cell<bool>, + writes_are_aligned: Cell<bool>, /// The current stack frame. Used to check accesses against locks. cur_frame: usize, @@ -287,8 +288,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { literal_alloc_cache: HashMap::new(), thread_local: BTreeMap::new(), next_thread_local: 0, - reads_are_aligned: true, - writes_are_aligned: true, + reads_are_aligned: Cell::new(true), + writes_are_aligned: Cell::new(true), cur_frame: usize::max_value(), } } @@ -796,7 +797,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { impl<'a, 'tcx> Memory<'a, 'tcx> { fn get_bytes_unchecked(&self, ptr: MemoryPointer, size: u64, align: u64) -> EvalResult<'tcx, &[u8]> { // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL - if self.reads_are_aligned { + if self.reads_are_aligned.get() { self.check_align(ptr.into(), align)?; } if size == 0 { @@ -813,7 +814,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { fn get_bytes_unchecked_mut(&mut self, ptr: MemoryPointer, size: u64, align: u64) -> EvalResult<'tcx, &mut [u8]> { // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL - if self.writes_are_aligned { + if self.writes_are_aligned.get() { self.check_align(ptr.into(), align)?; } if size == 0 { @@ -909,10 +910,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn copy(&mut self, src: Pointer, dest: Pointer, size: u64, align: u64, nonoverlapping: bool) -> EvalResult<'tcx> { if size == 0 { // Empty accesses don't need to be valid pointers, but they should still be aligned - if self.reads_are_aligned { + if self.reads_are_aligned.get() { self.check_align(src, align)?; } - if self.writes_are_aligned { + if self.writes_are_aligned.get() { self.check_align(dest, align)?; } return Ok(()); @@ -968,7 +969,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> { if size == 0 { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - if self.reads_are_aligned { + if self.reads_are_aligned.get() { self.check_align(ptr, 1)?; } return Ok(&[]); @@ -979,7 +980,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> { if src.is_empty() { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - if self.writes_are_aligned { + if self.writes_are_aligned.get() { self.check_align(ptr, 1)?; } return Ok(()); @@ -992,7 +993,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> { if count == 0 { // Empty accesses don't need to be valid pointers, but they should still be non-NULL - if self.writes_are_aligned { + if self.writes_are_aligned.get() { self.check_align(ptr, 1)?; } return Ok(()); @@ -1399,23 +1400,36 @@ pub(crate) trait HasMemory<'a, 'tcx> { fn memory(&self) -> &Memory<'a, 'tcx>; // These are not supposed to be overriden. - fn read_maybe_aligned<F, T>(&mut self, aligned: bool, f: F) -> EvalResult<'tcx, T> + fn read_maybe_aligned<F, T>(&self, aligned: bool, f: F) -> EvalResult<'tcx, T> + where F: FnOnce(&Self) -> EvalResult<'tcx, T> + { + let old = self.memory().reads_are_aligned.get(); + // Do alignment checking if *all* nested calls say it has to be aligned. + self.memory().reads_are_aligned.set(old && aligned); + let t = f(self); + self.memory().reads_are_aligned.set(old); + t + } + + fn read_maybe_aligned_mut<F, T>(&mut self, aligned: bool, f: F) -> EvalResult<'tcx, T> where F: FnOnce(&mut Self) -> EvalResult<'tcx, T> { - let old = self.memory_mut().reads_are_aligned; - self.memory_mut().reads_are_aligned = old && aligned; + let old = self.memory().reads_are_aligned.get(); + // Do alignment checking if *all* nested calls say it has to be aligned. + self.memory().reads_are_aligned.set(old && aligned); let t = f(self); - self.memory_mut().reads_are_aligned = old; + self.memory().reads_are_aligned.set(old); t } - fn write_maybe_aligned<F, T>(&mut self, aligned: bool, f: F) -> EvalResult<'tcx, T> + fn write_maybe_aligned_mut<F, T>(&mut self, aligned: bool, f: F) -> EvalResult<'tcx, T> where F: FnOnce(&mut Self) -> EvalResult<'tcx, T> { - let old = self.memory_mut().writes_are_aligned; - self.memory_mut().writes_are_aligned = old && aligned; + let old = self.memory().writes_are_aligned.get(); + // Do alignment checking if *all* nested calls say it has to be aligned. + self.memory().writes_are_aligned.set(old && aligned); let t = f(self); - self.memory_mut().writes_are_aligned = old; + self.memory().writes_are_aligned.set(old); t } } diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 075fab36f64..b78945155f1 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { trace!("struct wrapped nullable pointer type: {}", ty); // only the pointer part of a fat pointer is used for this space optimization let discr_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield"); - self.write_maybe_aligned(!packed, |ectx| ectx.memory.write_uint(nonnull, 0, discr_size))?; + self.write_maybe_aligned_mut(!packed, |ectx| ectx.memory.write_uint(nonnull, 0, discr_size))?; } }, diff --git a/src/librustc_mir/interpret/terminator/intrinsic.rs b/src/librustc_mir/interpret/terminator/intrinsic.rs index 2be5b7666f0..69dd41c82aa 100644 --- a/src/librustc_mir/interpret/terminator/intrinsic.rs +++ b/src/librustc_mir/interpret/terminator/intrinsic.rs @@ -45,7 +45,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "arith_offset" => { let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64; - let ptr = arg_vals[0].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; let result_ptr = self.wrapping_pointer_offset(ptr, substs.type_at(0), offset)?; self.write_ptr(dest, result_ptr, dest_ty)?; } @@ -61,7 +61,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "atomic_load_acq" | "volatile_load" => { let ty = substs.type_at(0); - let ptr = arg_vals[0].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; self.write_value(Value::by_ref(ptr), dest, ty)?; } @@ -70,7 +70,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "atomic_store_rel" | "volatile_store" => { let ty = substs.type_at(0); - let dest = arg_vals[0].into_ptr(&mut self.memory)?; + let dest = arg_vals[0].into_ptr(&self.memory)?; self.write_value_to_ptr(arg_vals[1], dest, ty)?; } @@ -80,7 +80,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].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; let change = self.value_to_primval(arg_vals[1], ty)?; let old = self.read_value(ptr, ty)?; let old = match old { @@ -94,7 +94,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { _ if intrinsic_name.starts_with("atomic_cxchg") => { let ty = substs.type_at(0); - let ptr = arg_vals[0].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_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)?; @@ -115,7 +115,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].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; let change = self.value_to_primval(arg_vals[1], ty)?; let old = self.read_value(ptr, ty)?; let old = match old { @@ -148,8 +148,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // TODO: We do not even validate alignment for the 0-bytes case. libstd relies on this in vec::IntoIter::next. // Also see the write_bytes intrinsic. let elem_align = self.type_align(elem_ty)?; - let src = arg_vals[0].into_ptr(&mut self.memory)?; - let dest = arg_vals[1].into_ptr(&mut self.memory)?; + let src = arg_vals[0].into_ptr(&self.memory)?; + let dest = arg_vals[1].into_ptr(&self.memory)?; self.memory.copy(src, dest, count * elem_size, elem_align, intrinsic_name.ends_with("_nonoverlapping"))?; } } @@ -176,7 +176,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "discriminant_value" => { let ty = substs.type_at(0); - let adt_ptr = arg_vals[0].into_ptr(&mut self.memory)?.to_ptr()?; + let adt_ptr = arg_vals[0].into_ptr(&self.memory)?.to_ptr()?; let discr_val = self.read_discriminant_value(adt_ptr, ty)?; self.write_primval(dest, PrimVal::Bytes(discr_val), dest_ty)?; } @@ -297,7 +297,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "move_val_init" => { let ty = substs.type_at(0); - let ptr = arg_vals[0].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; self.write_value_to_ptr(arg_vals[1], ptr, ty)?; } @@ -310,7 +310,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "offset" => { let offset = self.value_to_primval(arg_vals[1], isize)?.to_i128()? as i64; - let ptr = arg_vals[0].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; let result_ptr = self.pointer_offset(ptr, substs.type_at(0), offset)?; self.write_ptr(dest, result_ptr, dest_ty)?; } @@ -399,7 +399,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "transmute" => { let src_ty = substs.type_at(0); let ptr = self.force_allocation(dest)?.to_ptr()?; - self.write_maybe_aligned(/*aligned*/false, |ectx| { + self.write_maybe_aligned_mut(/*aligned*/false, |ectx| { ectx.write_value_to_ptr(arg_vals[0], ptr.into(), src_ty) })?; } @@ -464,7 +464,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ty_align = self.type_align(ty)?; let val_byte = self.value_to_primval(arg_vals[1], u8)?.to_u128()? as u8; let size = self.type_size(ty)?.expect("write_bytes() type must be sized"); - let ptr = arg_vals[0].into_ptr(&mut self.memory)?; + let ptr = arg_vals[0].into_ptr(&self.memory)?; let count = self.value_to_primval(arg_vals[2], usize)?.to_u64()?; if count > 0 { // HashMap relies on write_bytes on a NULL ptr with count == 0 to work @@ -550,7 +550,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok((size, align.abi())) } ty::TyDynamic(..) => { - let (_, vtable) = value.into_ptr_vtable_pair(&mut self.memory)?; + let (_, vtable) = value.into_ptr_vtable_pair(&self.memory)?; // the second entry in the vtable is the dynamic size of the object. self.read_size_and_align_from_vtable(vtable) } @@ -558,7 +558,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TySlice(_) | ty::TyStr => { let elem_ty = ty.sequence_element_type(self.tcx); let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized") as u64; - let (_, len) = value.into_slice(&mut self.memory)?; + let (_, len) = value.into_slice(&self.memory)?; let align = self.type_align(elem_ty)?; Ok((len * elem_size, align as u64)) } diff --git a/src/librustc_mir/interpret/terminator/mod.rs b/src/librustc_mir/interpret/terminator/mod.rs index e5b6d371381..b9b72ca34ac 100644 --- a/src/librustc_mir/interpret/terminator/mod.rs +++ b/src/librustc_mir/interpret/terminator/mod.rs @@ -397,7 +397,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }, ty::InstanceDef::Virtual(_, idx) => { let ptr_size = self.memory.pointer_size(); - let (_, vtable) = self.eval_operand(&arg_operands[0])?.into_ptr_vtable_pair(&mut self.memory)?; + let (_, vtable) = self.eval_operand(&arg_operands[0])?.into_ptr_vtable_pair(&self.memory)?; let fn_ptr = self.memory.read_ptr(vtable.offset(ptr_size * (idx as u64 + 3), &self)?)?; let instance = self.memory.get_fn(fn_ptr.to_ptr()?)?; let mut arg_operands = arg_operands.to_vec(); @@ -464,7 +464,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(false) } - pub fn read_discriminant_value(&mut self, adt_ptr: MemoryPointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { + pub fn read_discriminant_value(&self, adt_ptr: MemoryPointer, adt_ty: Ty<'tcx>) -> EvalResult<'tcx, u128> { use rustc::ty::layout::Layout::*; let adt_layout = self.type_layout(adt_ty)?; //trace!("read_discriminant_value {:#?}", adt_layout); @@ -577,7 +577,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.write_primval(dest, PrimVal::Ptr(ptr), dest_ty)?; } "alloc::heap::::__rust_dealloc" => { - let ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?; + let ptr = args[0].into_ptr(&self.memory)?.to_ptr()?; let old_size = self.value_to_primval(args[1], usize)?.to_u64()?; let align = self.value_to_primval(args[2], usize)?.to_u64()?; if old_size == 0 { @@ -589,7 +589,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.memory.deallocate(ptr, Some((old_size, align)), Kind::Rust)?; } "alloc::heap::::__rust_realloc" => { - let ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?; + let ptr = args[0].into_ptr(&self.memory)?.to_ptr()?; let old_size = self.value_to_primval(args[1], usize)?.to_u64()?; let old_align = self.value_to_primval(args[2], usize)?.to_u64()?; let new_size = self.value_to_primval(args[3], usize)?.to_u64()?; @@ -665,7 +665,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "free" => { - let ptr = args[0].into_ptr(&mut self.memory)?; + let ptr = args[0].into_ptr(&self.memory)?; if !ptr.is_null()? { self.memory.deallocate(ptr.to_ptr()?, None, Kind::C)?; } @@ -679,8 +679,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "dlsym" => { - let _handle = args[0].into_ptr(&mut self.memory)?; - let symbol = args[1].into_ptr(&mut self.memory)?.to_ptr()?; + let _handle = args[0].into_ptr(&self.memory)?; + let symbol = args[1].into_ptr(&self.memory)?.to_ptr()?; let symbol_name = self.memory.read_c_str(symbol)?; let err = format!("bad c unicode symbol: {:?}", symbol_name); let symbol_name = ::std::str::from_utf8(symbol_name).unwrap_or(&err); @@ -691,8 +691,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // fn __rust_maybe_catch_panic(f: fn(*mut u8), data: *mut u8, data_ptr: *mut usize, vtable_ptr: *mut usize) -> u32 // We abort on panic, so not much is going on here, but we still have to call the closure let u8_ptr_ty = self.tcx.mk_mut_ptr(self.tcx.types.u8); - let f = args[0].into_ptr(&mut self.memory)?.to_ptr()?; - let data = args[1].into_ptr(&mut self.memory)?; + let f = args[0].into_ptr(&self.memory)?.to_ptr()?; + let data = args[1].into_ptr(&self.memory)?; let f_instance = self.memory.get_fn(f)?; self.write_null(dest, dest_ty)?; @@ -723,8 +723,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "memcmp" => { - let left = args[0].into_ptr(&mut self.memory)?; - let right = args[1].into_ptr(&mut self.memory)?; + let left = args[0].into_ptr(&self.memory)?; + let right = args[1].into_ptr(&self.memory)?; let n = self.value_to_primval(args[2], usize)?.to_u64()?; let result = { @@ -743,7 +743,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "memrchr" => { - let ptr = args[0].into_ptr(&mut self.memory)?; + let ptr = args[0].into_ptr(&self.memory)?; let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) { @@ -755,7 +755,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "memchr" => { - let ptr = args[0].into_ptr(&mut self.memory)?; + let ptr = args[0].into_ptr(&self.memory)?; let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) { @@ -768,7 +768,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "getenv" => { let result = { - let name_ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?; + let name_ptr = args[0].into_ptr(&self.memory)?.to_ptr()?; let name = self.memory.read_c_str(name_ptr)?; match self.env_vars.get(name) { Some(&var) => PrimVal::Ptr(var), @@ -781,7 +781,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "unsetenv" => { let mut success = None; { - let name_ptr = args[0].into_ptr(&mut self.memory)?; + let name_ptr = args[0].into_ptr(&self.memory)?; if !name_ptr.is_null()? { let name = self.memory.read_c_str(name_ptr.to_ptr()?)?; if !name.is_empty() && !name.contains(&b'=') { @@ -802,8 +802,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "setenv" => { let mut new = None; { - let name_ptr = args[0].into_ptr(&mut self.memory)?; - let value_ptr = args[1].into_ptr(&mut self.memory)?.to_ptr()?; + let name_ptr = args[0].into_ptr(&self.memory)?; + let value_ptr = args[1].into_ptr(&self.memory)?.to_ptr()?; let value = self.memory.read_c_str(value_ptr)?; if !name_ptr.is_null()? { let name = self.memory.read_c_str(name_ptr.to_ptr()?)?; @@ -829,7 +829,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "write" => { let fd = self.value_to_primval(args[0], usize)?.to_u64()?; - let buf = args[1].into_ptr(&mut self.memory)?; + let buf = args[1].into_ptr(&self.memory)?; let n = self.value_to_primval(args[2], usize)?.to_u64()?; trace!("Called write({:?}, {:?}, {:?})", fd, buf, n); let result = if fd == 1 || fd == 2 { // stdout/stderr @@ -846,7 +846,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "strlen" => { - let ptr = args[0].into_ptr(&mut self.memory)?.to_ptr()?; + let ptr = args[0].into_ptr(&self.memory)?.to_ptr()?; let n = self.memory.read_c_str(ptr)?.len(); self.write_primval(dest, PrimVal::Bytes(n as u128), dest_ty)?; } @@ -889,10 +889,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // Hook pthread calls that go to the thread-local storage memory subsystem "pthread_key_create" => { - let key_ptr = args[0].into_ptr(&mut self.memory)?; + let key_ptr = args[0].into_ptr(&self.memory)?; // Extract the function type out of the signature (that seems easier than constructing it ourselves...) - let dtor = match args[1].into_ptr(&mut self.memory)?.into_inner_primval() { + let dtor = match args[1].into_ptr(&self.memory)?.into_inner_primval() { PrimVal::Ptr(dtor_ptr) => Some(self.memory.get_fn(dtor_ptr)?), PrimVal::Bytes(0) => None, PrimVal::Bytes(_) => return Err(EvalError::ReadBytesAsPointer), @@ -934,7 +934,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "pthread_setspecific" => { // The conversion into TlsKey here is a little fishy, but should work as long as usize >= libc::pthread_key_t let key = self.value_to_primval(args[0], usize)?.to_u64()? as TlsKey; - let new_ptr = args[1].into_ptr(&mut self.memory)?; + let new_ptr = args[1].into_ptr(&self.memory)?; self.memory.store_tls(key, new_ptr)?; // Return success (0) diff --git a/src/librustc_mir/interpret/validation.rs b/src/librustc_mir/interpret/validation.rs index 4c9e239299d..8c3cc185250 100644 --- a/src/librustc_mir/interpret/validation.rs +++ b/src/librustc_mir/interpret/validation.rs @@ -151,7 +151,7 @@ std::sync::atomic::AtomicBool::get_mut$|\ fn validate_ptr(&mut self, val: Value, pointee_ty: Ty<'tcx>, re: Option<CodeExtent>, mutbl: Mutability, mode: ValidationMode) -> EvalResult<'tcx> { // Check alignment and non-NULLness let (_, align) = self.size_and_align_of_dst(pointee_ty, val)?; - let ptr = val.into_ptr(&mut self.memory)?; + let ptr = val.into_ptr(&self.memory)?; self.memory.check_align(ptr, align)?; // Recurse @@ -309,7 +309,7 @@ std::sync::atomic::AtomicBool::get_mut$|\ self.validate_ptr(val, query.ty.boxed_ty(), query.re, query.mutbl, mode) } TyFnPtr(_sig) => { - let ptr = self.read_lvalue(query.lval)?.into_ptr(&mut self.memory)?.to_ptr()?; + let ptr = self.read_lvalue(query.lval)?.into_ptr(&self.memory)?.to_ptr()?; self.memory.get_fn(ptr)?; // TODO: Check if the signature matches (should be the same check as what terminator/mod.rs already does on call?). Ok(()) diff --git a/src/librustc_mir/interpret/value.rs b/src/librustc_mir/interpret/value.rs index a4115ddb5cc..302ea0abec3 100644 --- a/src/librustc_mir/interpret/value.rs +++ b/src/librustc_mir/interpret/value.rs @@ -167,7 +167,7 @@ impl<'a, 'tcx: 'a> Value { /// Convert the value into a pointer (or a pointer-sized integer). If the value is a ByRef, /// this may have to perform a load. - pub(super) fn into_ptr(&self, mem: &mut Memory<'a, 'tcx>) -> EvalResult<'tcx, Pointer> { + pub(super) fn into_ptr(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, Pointer> { use self::Value::*; match *self { ByRef(ptr, aligned) => { @@ -179,7 +179,7 @@ impl<'a, 'tcx: 'a> Value { pub(super) fn into_ptr_vtable_pair( &self, - mem: &mut Memory<'a, 'tcx> + mem: &Memory<'a, 'tcx> ) -> EvalResult<'tcx, (Pointer, MemoryPointer)> { use self::Value::*; match *self { @@ -197,11 +197,11 @@ impl<'a, 'tcx: 'a> Value { } } - pub(super) fn into_slice(&self, mem: &mut Memory<'a, 'tcx>) -> EvalResult<'tcx, (Pointer, u64)> { + pub(super) fn into_slice(&self, mem: &Memory<'a, 'tcx>) -> EvalResult<'tcx, (Pointer, u64)> { use self::Value::*; match *self { ByRef(ref_ptr, aligned) => { - mem.write_maybe_aligned(aligned, |mem| { + mem.read_maybe_aligned(aligned, |mem| { 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)) |
