diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 3a31aa4f36c..e8e3f09621d 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -169,14 +169,32 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // TODO(solson): Try making const_to_primval instead. fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> { use rustc::middle::const_val::ConstVal::*; + use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; + macro_rules! i2p { + ($i:ident, $n:expr) => {{ + let ptr = self.memory.allocate($n); + self.memory.write_int(ptr, $i as i64, $n)?; + Ok(ptr) + }} + } match *const_val { Float(_f) => unimplemented!(), - Integral(int) => { - // TODO(solson): Check int constant type. - let ptr = self.memory.allocate(8); - self.memory.write_uint(ptr, int.to_u64_unchecked(), 8)?; - Ok(ptr) - } + Integral(ConstInt::Infer(_)) => unreachable!(), + Integral(ConstInt::InferSigned(_)) => unreachable!(), + Integral(ConstInt::I8(i)) => i2p!(i, 1), + Integral(ConstInt::U8(i)) => i2p!(i, 1), + Integral(ConstInt::I16(i)) => i2p!(i, 2), + Integral(ConstInt::U16(i)) => i2p!(i, 2), + Integral(ConstInt::I32(i)) => i2p!(i, 4), + Integral(ConstInt::U32(i)) => i2p!(i, 4), + Integral(ConstInt::I64(i)) => i2p!(i, 8), + Integral(ConstInt::U64(i)) => i2p!(i, 8), + Integral(ConstInt::Isize(ConstIsize::Is16(i))) => i2p!(i, 2), + Integral(ConstInt::Isize(ConstIsize::Is32(i))) => i2p!(i, 4), + Integral(ConstInt::Isize(ConstIsize::Is64(i))) => i2p!(i, 8), + Integral(ConstInt::Usize(ConstUsize::Us16(i))) => i2p!(i, 2), + Integral(ConstInt::Usize(ConstUsize::Us32(i))) => i2p!(i, 4), + Integral(ConstInt::Usize(ConstUsize::Us64(i))) => i2p!(i, 8), Str(ref s) => { let psize = self.memory.pointer_size(); let static_ptr = self.memory.allocate(s.len()); diff --git a/src/memory.rs b/src/memory.rs index 89c7ad7b750..dd3c491e6b2 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,4 +1,4 @@ -use byteorder::{NativeEndian, ReadBytesExt, WriteBytesExt}; +use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian, BigEndian, self}; use std::collections::Bound::{Included, Excluded}; use std::collections::{btree_map, BTreeMap, HashMap, HashSet, VecDeque}; use std::{fmt, iter, mem, ptr}; @@ -6,7 +6,7 @@ use std::{fmt, iter, mem, ptr}; use rustc::hir::def_id::DefId; use rustc::ty::BareFnTy; use rustc::ty::subst::Substs; -use rustc::ty::layout::TargetDataLayout; +use rustc::ty::layout::{self, TargetDataLayout}; use error::{EvalError, EvalResult}; use primval::PrimVal; @@ -159,6 +159,10 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn pointer_size(&self) -> usize { self.layout.pointer_size.bytes() as usize } + + pub fn endianess(&self) -> layout::Endian { + self.layout.endian + } } /// Allocation accessors @@ -339,8 +343,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn read_ptr(&self, ptr: Pointer) -> EvalResult<'tcx, Pointer> { let size = self.pointer_size(); self.check_defined(ptr, size)?; - let offset = self.get_bytes_unchecked(ptr, size)? - .read_uint::(size).unwrap() as usize; + let endianess = self.endianess(); + let bytes = self.get_bytes_unchecked(ptr, size)?; + let offset = read_target_uint(endianess, bytes).unwrap() as usize; let alloc = self.get(ptr.alloc_id)?; match alloc.relocations.get(&ptr.offset) { Some(&alloc_id) => Ok(Pointer { alloc_id: alloc_id, offset: offset }), @@ -349,11 +354,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn write_ptr(&mut self, dest: Pointer, ptr: Pointer) -> EvalResult<'tcx, ()> { - { - let size = self.pointer_size(); - let mut bytes = self.get_bytes_mut(dest, size)?; - bytes.write_uint::(ptr.offset as u64, size).unwrap(); - } + self.write_usize(dest, ptr.offset as u64)?; self.get_mut(dest.alloc_id)?.relocations.insert(dest.offset, ptr.alloc_id); Ok(()) } @@ -391,19 +392,25 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn read_int(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, i64> { - self.get_bytes(ptr, size).map(|mut b| b.read_int::(size).unwrap()) + self.get_bytes(ptr, size).map(|b| read_target_int(self.endianess(), b).unwrap()) } pub fn write_int(&mut self, ptr: Pointer, n: i64, size: usize) -> EvalResult<'tcx, ()> { - self.get_bytes_mut(ptr, size).map(|mut b| b.write_int::(n, size).unwrap()) + let endianess = self.endianess(); + let b = self.get_bytes_mut(ptr, size)?; + write_target_int(endianess, b, n).unwrap(); + Ok(()) } pub fn read_uint(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, u64> { - self.get_bytes(ptr, size).map(|mut b| b.read_uint::(size).unwrap()) + self.get_bytes(ptr, size).map(|b| read_target_uint(self.endianess(), b).unwrap()) } pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: usize) -> EvalResult<'tcx, ()> { - self.get_bytes_mut(ptr, size).map(|mut b| b.write_uint::(n, size).unwrap()) + let endianess = self.endianess(); + let b = self.get_bytes_mut(ptr, size)?; + write_target_uint(endianess, b, n).unwrap(); + Ok(()) } pub fn read_isize(&self, ptr: Pointer) -> EvalResult<'tcx, i64> { @@ -513,6 +520,38 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } } +//////////////////////////////////////////////////////////////////////////////// +// Methods to access integers in the target endianess +//////////////////////////////////////////////////////////////////////////////// + +fn write_target_uint(endianess: layout::Endian, mut target: &mut [u8], data: u64) -> Result<(), byteorder::Error> { + let len = target.len(); + match endianess { + layout::Endian::Little => target.write_uint::(data, len), + layout::Endian::Big => target.write_uint::(data, len), + } +} +fn write_target_int(endianess: layout::Endian, mut target: &mut [u8], data: i64) -> Result<(), byteorder::Error> { + let len = target.len(); + match endianess { + layout::Endian::Little => target.write_int::(data, len), + layout::Endian::Big => target.write_int::(data, len), + } +} + +fn read_target_uint(endianess: layout::Endian, mut source: &[u8]) -> Result { + match endianess { + layout::Endian::Little => source.read_uint::(source.len()), + layout::Endian::Big => source.read_uint::(source.len()), + } +} +fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result { + match endianess { + layout::Endian::Little => source.read_int::(source.len()), + layout::Endian::Big => source.read_int::(source.len()), + } +} + //////////////////////////////////////////////////////////////////////////////// // Undefined byte tracking ////////////////////////////////////////////////////////////////////////////////