if key_size.bits() < 128 && key >= (1u128 << key_size.bits() as u128) {
return err!(OutOfTls);
}
- // TODO: Does this need checking for alignment?
- self.memory.write_uint(
+ self.memory.write_primval(
key_ptr.to_ptr()?,
- key,
+ PrimVal::Bytes(key),
key_size.bytes(),
+ false,
)?;
// Return success (0)
discr_val: u128,
variant_idx: usize,
discr_size: u64,
+ discr_signed: bool,
) -> EvalResult<'tcx> {
// FIXME(solson)
let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
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 {
ptr: PtrAndAlign {
discr_val,
variant,
discr_size,
+ false,
)?;
} else {
bug!("tried to assign {:?} to Layout::General", kind);
);
self.memory.write_maybe_aligned_mut(
!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 {
}
Value::ByVal(primval) => {
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),
}
);
let field_0_ptr = ptr.offset(field_0.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| {
- 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| {
- ectx.memory.write_primval(field_1_ptr, b, field_1_size)
+ ectx.memory.write_primval(field_1_ptr, b, field_1_size, false)
})?;
Ok(())
}
self.read_primval(ptr, self.pointer_size(), false)
}
- pub fn write_ptr(&mut self, dest: MemoryPointer, ptr: MemoryPointer) -> EvalResult<'tcx> {
- self.write_usize(dest, ptr.offset as u64)?;
- self.get_mut(dest.alloc_id)?.relocations.insert(
- dest.offset,
- ptr.alloc_id,
- );
- Ok(())
- }
+ pub fn write_primval(&mut self, ptr: MemoryPointer, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
+ trace!("Writing {:?}, size {}", val, size);
+ let align = self.int_align(size)?;
+ let endianess = self.endianess();
- pub fn write_primval(&mut self, dest: Pointer, val: PrimVal, size: u64) -> EvalResult<'tcx> {
- match val {
- PrimVal::Ptr(ptr) => {
+ let bytes = match val {
+ PrimVal::Ptr(val) => {
assert_eq!(size, self.pointer_size());
- self.write_ptr(dest.to_ptr()?, ptr)
+ val.offset as u128
}
PrimVal::Bytes(bytes) => {
16 => !0,
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 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> {
let endianess = self.endianess();
let align = self.layout.f32_align.abi();
use rustc::ty::subst::Substs;
use super::{EvalResult, EvalContext, StackPopCleanup, TyAndPacked, PtrAndAlign, GlobalId, Lvalue,
- HasMemory, MemoryKind, Machine};
+ HasMemory, MemoryKind, Machine, PrimVal};
use syntax::codemap::Span;
use syntax::ast::Mutability;
Layout::General { discr, .. } => {
let discr_size = discr.size().bytes();
let dest_ptr = self.force_allocation(dest)?.to_ptr()?;
- self.memory.write_uint(
+ self.memory.write_primval(
dest_ptr,
- variant_index as u128,
+ PrimVal::Bytes(variant_index as u128),
discr_size,
+ false
)?
}
ref discrfield_source,
..
} => {
+ // TODO: There's some duplication between here and eval_rvalue_into_lvalue
if variant_index as u64 != nndiscr {
let (offset, TyAndPacked { ty, packed }) = self.nonnull_offset_and_ty(
dest_ty,
"bad StructWrappedNullablePointer discrfield",
);
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)
})?;
}
}
ptr_size,
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.globals.insert(
cid,
let drop = eval_context::resolve_drop_in_place(self.tcx, ty);
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)?;
- 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)?;
- 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() {
if let Some((def_id, substs)) = method {
let instance = eval_context::resolve(self.tcx, def_id, substs);
let fn_ptr = self.memory.create_fn_alloc(instance);
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))?;
}
}