use syntax::ast::{IntTy, UintTy};
let repr = match ty.sty {
ty::TyBool => Repr::Primitive { size: 1 },
- ty::TyInt(IntTy::Is) => Repr::isize(),
+ ty::TyInt(IntTy::Is) => Repr::Primitive { size: self.memory.pointer_size },
ty::TyInt(IntTy::I8) => Repr::Primitive { size: 1 },
ty::TyInt(IntTy::I16) => Repr::Primitive { size: 2 },
ty::TyInt(IntTy::I32) => Repr::Primitive { size: 4 },
ty::TyInt(IntTy::I64) => Repr::Primitive { size: 8 },
- ty::TyUint(UintTy::Us) => Repr::usize(),
+ ty::TyUint(UintTy::Us) => Repr::Primitive { size: self.memory.pointer_size },
ty::TyUint(UintTy::U8) => Repr::Primitive { size: 1 },
ty::TyUint(UintTy::U16) => Repr::Primitive { size: 2 },
ty::TyUint(UintTy::U32) => Repr::Primitive { size: 4 },
ty::TyRawPtr(ty::TypeAndMut { ty, .. }) |
ty::TyBox(ty) => {
if ty.is_sized(&self.tcx.empty_parameter_environment(), DUMMY_SP) {
- Repr::Pointer
+ Repr::Primitive { size: self.memory.pointer_size }
} else {
- Repr::FatPointer
+ Repr::Primitive { size: self.memory.pointer_size * 2 }
}
}
use error::{EvalError, EvalResult};
use primval::PrimVal;
-// TODO(tsion): How should this get set? Host or target pointer size?
-const POINTER_SIZE: usize = 8;
-
pub struct Memory {
- next_id: u64,
alloc_map: HashMap<u64, Allocation>,
+ next_id: u64,
+ pub pointer_size: usize,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Repr {
- /// Representation for a primitive type such as a boolean, integer, or character.
+ /// Representation for a non-aggregate type such as a boolean, integer, character or pointer.
Primitive {
size: usize
},
- Pointer,
- FatPointer,
-
/// The representation for aggregate types including structs, enums, and tuples.
Aggregate {
/// The size of the discriminant (an integer). Should be between 0 and 8. Always 0 for
impl Memory {
pub fn new() -> Self {
- Memory { next_id: 0, alloc_map: HashMap::new() }
+ Memory {
+ alloc_map: HashMap::new(),
+ next_id: 0,
+
+ // TODO(tsion): Should this be host's or target's usize?
+ pointer_size: mem::size_of::<usize>(),
+ }
}
pub fn allocate(&mut self, size: usize) -> Pointer {
pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<Pointer> {
let alloc = try!(self.get(ptr.alloc_id));
- try!(alloc.check_relocation_edges(ptr.offset, ptr.offset + POINTER_SIZE));
- let bytes = &alloc.bytes[ptr.offset..ptr.offset + POINTER_SIZE];
+ try!(alloc.check_relocation_edges(ptr.offset, ptr.offset + self.pointer_size));
+ let bytes = &alloc.bytes[ptr.offset..ptr.offset + self.pointer_size];
let offset = byteorder::NativeEndian::read_u64(bytes) as usize;
match alloc.relocations.get(&ptr.offset) {
// TODO(tsion): Detect invalid writes here and elsewhere.
pub fn write_ptr(&mut self, dest: Pointer, ptr_val: Pointer) -> EvalResult<()> {
{
- let bytes = try!(self.get_bytes_mut(dest, POINTER_SIZE));
+ let size = self.pointer_size;
+ let bytes = try!(self.get_bytes_mut(dest, size));
byteorder::NativeEndian::write_u64(bytes, ptr_val.offset as u64);
}
let alloc = try!(self.get_mut(dest.alloc_id));
ty::TyUint(UintTy::U64) => self.read_uint(ptr, 8).map(|n| PrimVal::U64(n as u64)),
// TODO(tsion): Pick the PrimVal dynamically.
- ty::TyInt(IntTy::Is) => self.read_int(ptr, POINTER_SIZE).map(PrimVal::I64),
- ty::TyUint(UintTy::Us) => self.read_uint(ptr, POINTER_SIZE).map(PrimVal::U64),
+ ty::TyInt(IntTy::Is) => self.read_int(ptr, self.pointer_size).map(PrimVal::I64),
+ ty::TyUint(UintTy::Us) => self.read_uint(ptr, self.pointer_size).map(PrimVal::U64),
_ => panic!("primitive read of non-primitive type: {:?}", ty),
}
}
fn count_overlapping_relocations(&self, start: usize, end: usize) -> usize {
self.relocations.range(
- Included(&start.saturating_sub(POINTER_SIZE - 1)),
+ // FIXME(tsion): Assuming pointer size is 8. Move this method to Memory.
+ Included(&start.saturating_sub(8 - 1)),
Excluded(&end)
).count()
}
}
impl Repr {
- // TODO(tsion): Choice is based on host machine's type size. Should this be how miri works?
- pub fn isize() -> Self {
- Repr::Primitive { size: mem::size_of::<isize>() }
- }
-
- // TODO(tsion): Choice is based on host machine's type size. Should this be how miri works?
- pub fn usize() -> Self {
- Repr::Primitive { size: mem::size_of::<usize>() }
- }
-
pub fn size(&self) -> usize {
match *self {
Repr::Primitive { size } => size,
Repr::Aggregate { size, .. } => size,
Repr::Array { elem_size, length } => elem_size * length,
- Repr::Pointer => POINTER_SIZE,
- Repr::FatPointer => POINTER_SIZE * 2,
}
}
}