refactor memory write API to match read API

This commit is contained in:
Ralf Jung 2017-08-25 18:25:05 +02:00
parent f036fe0d32
commit b1ca65447a
5 changed files with 76 additions and 57 deletions

View File

@ -421,11 +421,11 @@ impl<'a, 'tcx> EvalContextExt<'tcx> for EvalContext<'a, 'tcx, super::Evaluator>
if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) { if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
return err!(OutOfTls); return err!(OutOfTls);
} }
// TODO: Does this need checking for alignment? self.memory.write_primval(
self.memory.write_uint(
key_ptr.to_ptr()?, key_ptr.to_ptr()?,
key, PrimVal::Bytes(key),
key_size.bytes(), key_size.bytes(),
false,
)?; )?;
// Return success (0) // Return success (0)

View File

@ -579,12 +579,13 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
discr_val: u128, discr_val: u128,
variant_idx: usize, variant_idx: usize,
discr_size: u64, discr_size: u64,
discr_signed: bool,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
// FIXME(solson) // FIXME(solson)
let dest_ptr = self.force_allocation(dest)?.to_ptr()?; let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
let discr_dest = dest_ptr.offset(discr_offset, &self)?; let discr_dest = dest_ptr.offset(discr_offset, &self)?;
self.memory.write_uint(discr_dest, discr_val, discr_size)?; self.memory.write_primval(discr_dest, PrimVal::Bytes(discr_val), discr_size, discr_signed)?;
let dest = Lvalue::Ptr { let dest = Lvalue::Ptr {
ptr: PtrAndAlign { ptr: PtrAndAlign {
@ -724,6 +725,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
discr_val, discr_val,
variant, variant,
discr_size, discr_size,
false,
)?; )?;
} else { } else {
bug!("tried to assign {:?} to Layout::General", kind); bug!("tried to assign {:?} to Layout::General", kind);
@ -783,7 +785,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
); );
self.memory.write_maybe_aligned_mut( self.memory.write_maybe_aligned_mut(
!nonnull.packed, !nonnull.packed,
|mem| mem.write_int(dest, 0, dest_size), // The sign does not matter for 0
|mem| mem.write_primval(dest, PrimVal::Bytes(0), dest_size, false),
)?; )?;
} }
} else { } else {
@ -1607,7 +1610,20 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
} }
Value::ByVal(primval) => { Value::ByVal(primval) => {
let size = self.type_size(dest_ty)?.expect("dest type must be sized"); let size = self.type_size(dest_ty)?.expect("dest type must be sized");
self.memory.write_primval(dest, primval, size) // TODO: This fn gets called with sizes like 6, which cannot be a primitive type
// and hence is not supported by write_primval.
// (E.g. in the arrays.rs testcase.) That seems to only happen for Undef though,
// so we special-case that here.
match primval {
PrimVal::Undef => {
self.memory.mark_definedness(dest, size, false)?;
}
_ => {
// TODO: Do we need signedness?
self.memory.write_primval(dest.to_ptr()?, primval, size, false)?;
}
}
Ok(())
} }
Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest.to_ptr()?, dest_ty), Value::ByValPair(a, b) => self.write_pair_to_ptr(a, b, dest.to_ptr()?, dest_ty),
} }
@ -1645,11 +1661,12 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
); );
let field_0_ptr = ptr.offset(field_0.bytes(), &self)?.into(); let field_0_ptr = ptr.offset(field_0.bytes(), &self)?.into();
let field_1_ptr = ptr.offset(field_1.bytes(), &self)?.into(); let field_1_ptr = ptr.offset(field_1.bytes(), &self)?.into();
// TODO: What about signedess?
self.write_maybe_aligned_mut(!packed, |ectx| { self.write_maybe_aligned_mut(!packed, |ectx| {
ectx.memory.write_primval(field_0_ptr, a, field_0_size) ectx.memory.write_primval(field_0_ptr, a, field_0_size, false)
})?; })?;
self.write_maybe_aligned_mut(!packed, |ectx| { self.write_maybe_aligned_mut(!packed, |ectx| {
ectx.memory.write_primval(field_1_ptr, b, field_1_size) ectx.memory.write_primval(field_1_ptr, b, field_1_size, false)
})?; })?;
Ok(()) Ok(())
} }

View File

@ -1206,20 +1206,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
self.read_primval(ptr, self.pointer_size(), false) self.read_primval(ptr, self.pointer_size(), false)
} }
pub fn write_ptr(&mut self, dest: MemoryPointer, ptr: MemoryPointer) -> EvalResult<'tcx> { pub fn write_primval(&mut self, ptr: MemoryPointer, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
self.write_usize(dest, ptr.offset as u64)?; trace!("Writing {:?}, size {}", val, size);
self.get_mut(dest.alloc_id)?.relocations.insert( let align = self.int_align(size)?;
dest.offset, let endianess = self.endianess();
ptr.alloc_id,
);
Ok(())
}
pub fn write_primval(&mut self, dest: Pointer, val: PrimVal, size: u64) -> EvalResult<'tcx> { let bytes = match val {
match val { PrimVal::Ptr(val) => {
PrimVal::Ptr(ptr) => {
assert_eq!(size, self.pointer_size()); assert_eq!(size, self.pointer_size());
self.write_ptr(dest.to_ptr()?, ptr) val.offset as u128
} }
PrimVal::Bytes(bytes) => { PrimVal::Bytes(bytes) => {
@ -1233,11 +1228,41 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
16 => !0, 16 => !0,
n => bug!("unexpected PrimVal::Bytes size: {}", n), n => bug!("unexpected PrimVal::Bytes size: {}", n),
}; };
self.write_uint(dest.to_ptr()?, bytes & mask, size) bytes & mask
} }
PrimVal::Undef => self.mark_definedness(dest, size, false), PrimVal::Undef => {
self.mark_definedness(PrimVal::Ptr(ptr).into(), size, false)?;
return Ok(());
} }
};
{
let dst = self.get_bytes_mut(ptr, size, align)?;
if signed {
write_target_int(endianess, dst, bytes as i128).unwrap();
} else {
write_target_uint(endianess, dst, bytes).unwrap();
}
}
// See if we have to also write a relocation
match val {
PrimVal::Ptr(val) => {
self.get_mut(ptr.alloc_id)?.relocations.insert(
ptr.offset,
val.alloc_id,
);
}
_ => {}
}
Ok(())
}
pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, val: PrimVal) -> EvalResult<'tcx> {
let ptr_size = self.pointer_size();
self.write_primval(ptr, val, ptr_size, false)
} }
pub fn read_bool(&self, ptr: MemoryPointer) -> EvalResult<'tcx, bool> { pub fn read_bool(&self, ptr: MemoryPointer) -> EvalResult<'tcx, bool> {
@ -1269,32 +1294,6 @@ impl<'a, 'tcx, M: Machine<'tcx>> Memory<'a, 'tcx, M> {
} }
} }
pub fn write_int(&mut self, ptr: MemoryPointer, n: i128, size: u64) -> EvalResult<'tcx> {
let align = self.int_align(size)?;
let endianess = self.endianess();
let b = self.get_bytes_mut(ptr, size, align)?;
write_target_int(endianess, b, n).unwrap();
Ok(())
}
pub fn write_uint(&mut self, ptr: MemoryPointer, n: u128, size: u64) -> EvalResult<'tcx> {
let align = self.int_align(size)?;
let endianess = self.endianess();
let b = self.get_bytes_mut(ptr, size, align)?;
write_target_uint(endianess, b, n).unwrap();
Ok(())
}
pub fn write_isize(&mut self, ptr: MemoryPointer, n: i64) -> EvalResult<'tcx> {
let size = self.pointer_size();
self.write_int(ptr, n as i128, size)
}
pub fn write_usize(&mut self, ptr: MemoryPointer, n: u64) -> EvalResult<'tcx> {
let size = self.pointer_size();
self.write_uint(ptr, n as u128, size)
}
pub fn write_f32(&mut self, ptr: MemoryPointer, f: f32) -> EvalResult<'tcx> { pub fn write_f32(&mut self, ptr: MemoryPointer, f: f32) -> EvalResult<'tcx> {
let endianess = self.endianess(); let endianess = self.endianess();
let align = self.layout.f32_align.abi(); let align = self.layout.f32_align.abi();

View File

@ -12,7 +12,7 @@ use rustc::ty::layout::Layout;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use super::{EvalResult, EvalContext, StackPopCleanup, TyAndPacked, PtrAndAlign, GlobalId, Lvalue, use super::{EvalResult, EvalContext, StackPopCleanup, TyAndPacked, PtrAndAlign, GlobalId, Lvalue,
HasMemory, MemoryKind, Machine}; HasMemory, MemoryKind, Machine, PrimVal};
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::ast::Mutability; use syntax::ast::Mutability;
@ -106,10 +106,11 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
Layout::General { discr, .. } => { Layout::General { discr, .. } => {
let discr_size = discr.size().bytes(); let discr_size = discr.size().bytes();
let dest_ptr = self.force_allocation(dest)?.to_ptr()?; let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
self.memory.write_uint( self.memory.write_primval(
dest_ptr, dest_ptr,
variant_index as u128, PrimVal::Bytes(variant_index as u128),
discr_size, discr_size,
false
)? )?
} }
@ -124,6 +125,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
ref discrfield_source, ref discrfield_source,
.. ..
} => { } => {
// TODO: There's some duplication between here and eval_rvalue_into_lvalue
if variant_index as u64 != nndiscr { if variant_index as u64 != nndiscr {
let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty( let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(
dest_ty, dest_ty,
@ -140,7 +142,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
"bad StructWrappedNullablePointer discrfield", "bad StructWrappedNullablePointer discrfield",
); );
self.write_maybe_aligned_mut(!packed, |ectx| { self.write_maybe_aligned_mut(!packed, |ectx| {
ectx.memory.write_uint(nonnull, 0, discr_size) // We're writing 0, signedness does not matter
ectx.memory.write_primval(nonnull, PrimVal::Bytes(0), discr_size, false)
})?; })?;
} }
} }
@ -229,7 +232,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
ptr_size, ptr_size,
MemoryKind::UninitializedStatic, MemoryKind::UninitializedStatic,
)?; )?;
self.memory.write_usize(ptr, 0)?; self.memory.write_ptr_sized_unsigned(ptr, PrimVal::Bytes(0))?;
self.memory.mark_static_initalized(ptr.alloc_id, mutability)?; self.memory.mark_static_initalized(ptr.alloc_id, mutability)?;
self.globals.insert( self.globals.insert(
cid, cid,

View File

@ -63,19 +63,19 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
let drop = eval_context::resolve_drop_in_place(self.tcx, ty); let drop = eval_context::resolve_drop_in_place(self.tcx, ty);
let drop = self.memory.create_fn_alloc(drop); let drop = self.memory.create_fn_alloc(drop);
self.memory.write_ptr(vtable, drop)?; self.memory.write_ptr_sized_unsigned(vtable, PrimVal::Ptr(drop))?;
let size_ptr = vtable.offset(ptr_size, &self)?; let size_ptr = vtable.offset(ptr_size, &self)?;
self.memory.write_usize(size_ptr, size)?; self.memory.write_ptr_sized_unsigned(size_ptr, PrimVal::Bytes(size as u128))?;
let align_ptr = vtable.offset(ptr_size * 2, &self)?; let align_ptr = vtable.offset(ptr_size * 2, &self)?;
self.memory.write_usize(align_ptr, align)?; self.memory.write_ptr_sized_unsigned(align_ptr, PrimVal::Bytes(align as u128))?;
for (i, method) in ::rustc::traits::get_vtable_methods(self.tcx, trait_ref).enumerate() { for (i, method) in ::rustc::traits::get_vtable_methods(self.tcx, trait_ref).enumerate() {
if let Some((def_id, substs)) = method { if let Some((def_id, substs)) = method {
let instance = eval_context::resolve(self.tcx, def_id, substs); let instance = eval_context::resolve(self.tcx, def_id, substs);
let fn_ptr = self.memory.create_fn_alloc(instance); let fn_ptr = self.memory.create_fn_alloc(instance);
let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?; let method_ptr = vtable.offset(ptr_size * (3 + i as u64), &self)?;
self.memory.write_ptr(method_ptr, fn_ptr)?; self.memory.write_ptr_sized_unsigned(method_ptr, PrimVal::Ptr(fn_ptr))?;
} }
} }