Choose pointer size dynamically.
This commit is contained in:
parent
0b37be71c2
commit
12457607c3
2 changed files with 22 additions and 31 deletions
|
|
@ -582,13 +582,13 @@ impl<'a, 'tcx: 'a, 'arena> Interpreter<'a, 'tcx, 'arena> {
|
|||
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 },
|
||||
|
|
@ -613,9 +613,9 @@ impl<'a, 'tcx: 'a, 'arena> Interpreter<'a, 'tcx, 'arena> {
|
|||
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 }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,12 +8,10 @@ use std::ptr;
|
|||
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)]
|
||||
|
|
@ -40,14 +38,11 @@ pub struct FieldRepr {
|
|||
|
||||
#[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
|
||||
|
|
@ -71,7 +66,13 @@ pub enum Repr {
|
|||
|
||||
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 {
|
||||
|
|
@ -145,8 +146,8 @@ impl Memory {
|
|||
|
||||
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) {
|
||||
|
|
@ -158,7 +159,8 @@ impl Memory {
|
|||
// 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));
|
||||
|
|
@ -180,8 +182,8 @@ impl Memory {
|
|||
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),
|
||||
}
|
||||
}
|
||||
|
|
@ -241,7 +243,8 @@ impl Allocation {
|
|||
|
||||
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()
|
||||
}
|
||||
|
|
@ -275,23 +278,11 @@ impl Pointer {
|
|||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue