]> git.lizzy.rs Git - rust.git/commitdiff
Use `Size` instead of `u64` in mir interpretation
authorOliver Schneider <github35764891676564198441@oli-obk.de>
Sat, 19 May 2018 14:37:29 +0000 (16:37 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Sat, 19 May 2018 14:38:49 +0000 (16:38 +0200)
17 files changed:
src/librustc/mir/interpret/error.rs
src/librustc/mir/interpret/mod.rs
src/librustc/mir/interpret/value.rs
src/librustc/mir/mod.rs
src/librustc_codegen_llvm/mir/constant.rs
src/librustc_codegen_llvm/mir/operand.rs
src/librustc_mir/hair/cx/mod.rs
src/librustc_mir/hair/pattern/_match.rs
src/librustc_mir/hair/pattern/mod.rs
src/librustc_mir/interpret/cast.rs
src/librustc_mir/interpret/const_eval.rs
src/librustc_mir/interpret/eval_context.rs
src/librustc_mir/interpret/machine.rs
src/librustc_mir/interpret/memory.rs
src/librustc_mir/interpret/place.rs
src/librustc_mir/interpret/terminator/mod.rs
src/librustc_target/abi/mod.rs

index 1e1d50c3fc036d36d26369c18ed4d5ffdfc19db7..6885bf89cc8b6806a4965f10159ee7357d9c2f14 100644 (file)
@@ -2,6 +2,7 @@
 
 use mir;
 use ty::{FnSig, Ty, layout};
+use ty::layout::{Size, Align};
 
 use super::{
     MemoryPointer, Lock, AccessKind
@@ -47,7 +48,7 @@ pub enum EvalErrorKind<'tcx, O> {
     PointerOutOfBounds {
         ptr: MemoryPointer,
         access: bool,
-        allocation_size: u64,
+        allocation_size: Size,
     },
     InvalidNullPointerUsage,
     ReadPointerAsBytes,
@@ -71,8 +72,8 @@ pub enum EvalErrorKind<'tcx, O> {
     TlsOutOfBounds,
     AbiViolation(String),
     AlignmentCheckFailed {
-        required: u64,
-        has: u64,
+        required: Align,
+        has: Align,
     },
     MemoryLockViolation {
         ptr: MemoryPointer,
@@ -108,7 +109,7 @@ pub enum EvalErrorKind<'tcx, O> {
     DeallocatedWrongMemoryKind(String, String),
     ReallocateNonBasePtr,
     DeallocateNonBasePtr,
-    IncorrectAllocationInformation(u64, usize, u64, u64),
+    IncorrectAllocationInformation(Size, Size, Align, Align),
     Layout(layout::LayoutError<'tcx>),
     HeapAllocZeroBytes,
     HeapAllocNonPowerOfTwoAlignment(u64),
@@ -269,7 +270,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             PointerOutOfBounds { ptr, access, allocation_size } => {
                 write!(f, "{} at offset {}, outside bounds of allocation {} which has size {}",
                        if access { "memory access" } else { "pointer computed" },
-                       ptr.offset, ptr.alloc_id, allocation_size)
+                       ptr.offset.bytes(), ptr.alloc_id, allocation_size.bytes())
             },
             MemoryLockViolation { ptr, len, frame, access, ref lock } => {
                 write!(f, "{:?} access by frame {} at {:?}, size {}, is in conflict with lock {:?}",
@@ -305,7 +306,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                 write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
             AlignmentCheckFailed { required, has } =>
                write!(f, "tried to access memory with alignment {}, but alignment {} is required",
-                      has, required),
+                      has.abi(), required.abi()),
             TypeNotPrimitive(ty) =>
                 write!(f, "expected primitive type, got {}", ty),
             Layout(ref err) =>
@@ -315,7 +316,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             MachineError(ref inner) =>
                 write!(f, "{}", inner),
             IncorrectAllocationInformation(size, size2, align, align2) =>
-                write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size, align, size2, align2),
+                write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()),
             _ => write!(f, "{}", self.description()),
         }
     }
index 31885c1e0205ed553ed3ee2ffbaa72211b1a857b..d4f18acf8ad5404d961f9591ff2b4ffe0791a915 100644 (file)
@@ -17,7 +17,7 @@ macro_rules! err {
 use mir;
 use hir::def_id::DefId;
 use ty::{self, TyCtxt};
-use ty::layout::{self, Align, HasDataLayout};
+use ty::layout::{self, Align, HasDataLayout, Size};
 use middle::region;
 use std::iter;
 use std::io;
@@ -109,42 +109,42 @@ impl<T: layout::HasDataLayout> PointerArithmetic for T {}
 #[derive(Copy, Clone, Debug, Eq, PartialEq, RustcEncodable, RustcDecodable, Hash)]
 pub struct MemoryPointer {
     pub alloc_id: AllocId,
-    pub offset: u64,
+    pub offset: Size,
 }
 
 impl<'tcx> MemoryPointer {
-    pub fn new(alloc_id: AllocId, offset: u64) -> Self {
+    pub fn new(alloc_id: AllocId, offset: Size) -> Self {
         MemoryPointer { alloc_id, offset }
     }
 
     pub(crate) fn wrapping_signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> Self {
         MemoryPointer::new(
             self.alloc_id,
-            cx.data_layout().wrapping_signed_offset(self.offset, i),
+            Size::from_bytes(cx.data_layout().wrapping_signed_offset(self.offset.bytes(), i)),
         )
     }
 
     pub fn overflowing_signed_offset<C: HasDataLayout>(self, i: i128, cx: C) -> (Self, bool) {
-        let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset, i);
-        (MemoryPointer::new(self.alloc_id, res), over)
+        let (res, over) = cx.data_layout().overflowing_signed_offset(self.offset.bytes(), i);
+        (MemoryPointer::new(self.alloc_id, Size::from_bytes(res)), over)
     }
 
     pub(crate) fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx, Self> {
         Ok(MemoryPointer::new(
             self.alloc_id,
-            cx.data_layout().signed_offset(self.offset, i)?,
+            Size::from_bytes(cx.data_layout().signed_offset(self.offset.bytes(), i)?),
         ))
     }
 
-    pub fn overflowing_offset<C: HasDataLayout>(self, i: u64, cx: C) -> (Self, bool) {
-        let (res, over) = cx.data_layout().overflowing_offset(self.offset, i);
-        (MemoryPointer::new(self.alloc_id, res), over)
+    pub fn overflowing_offset<C: HasDataLayout>(self, i: Size, cx: C) -> (Self, bool) {
+        let (res, over) = cx.data_layout().overflowing_offset(self.offset.bytes(), i.bytes());
+        (MemoryPointer::new(self.alloc_id, Size::from_bytes(res)), over)
     }
 
-    pub fn offset<C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
+    pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
         Ok(MemoryPointer::new(
             self.alloc_id,
-            cx.data_layout().offset(self.offset, i)?,
+            Size::from_bytes(cx.data_layout().offset(self.offset.bytes(), i.bytes())?),
         ))
     }
 }
@@ -244,7 +244,7 @@ pub struct Allocation {
     pub bytes: Vec<u8>,
     /// Maps from byte addresses to allocations.
     /// Only the first byte of a pointer is inserted into the map.
-    pub relocations: BTreeMap<u64, AllocId>,
+    pub relocations: BTreeMap<Size, AllocId>,
     /// Denotes undefined memory. Reading from undefined memory is forbidden in miri
     pub undef_mask: UndefMask,
     /// The alignment of the allocation to detect unaligned reads.
@@ -257,8 +257,8 @@ pub struct Allocation {
 
 impl Allocation {
     pub fn from_bytes(slice: &[u8], align: Align) -> Self {
-        let mut undef_mask = UndefMask::new(0);
-        undef_mask.grow(slice.len() as u64, true);
+        let mut undef_mask = UndefMask::new(Size::from_bytes(0));
+        undef_mask.grow(Size::from_bytes(slice.len() as u64), true);
         Self {
             bytes: slice.to_owned(),
             relocations: BTreeMap::new(),
@@ -272,10 +272,10 @@ pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self {
         Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
     }
 
-    pub fn undef(size: u64, align: Align) -> Self {
-        assert_eq!(size as usize as u64, size);
+    pub fn undef(size: Size, align: Align) -> Self {
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
         Allocation {
-            bytes: vec![0; size as usize],
+            bytes: vec![0; size.bytes() as usize],
             relocations: BTreeMap::new(),
             undef_mask: UndefMask::new(size),
             align,
@@ -331,35 +331,35 @@ pub fn read_target_uint(endianness: layout::Endian, mut source: &[u8]) -> Result
 #[derive(Clone, Debug, Eq, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct UndefMask {
     blocks: Vec<Block>,
-    len: u64,
+    len: Size,
 }
 
 impl_stable_hash_for!(struct mir::interpret::UndefMask{blocks, len});
 
 impl UndefMask {
-    pub fn new(size: u64) -> Self {
+    pub fn new(size: Size) -> Self {
         let mut m = UndefMask {
             blocks: vec![],
-            len: 0,
+            len: Size::from_bytes(0),
         };
         m.grow(size, false);
         m
     }
 
     /// Check whether the range `start..end` (end-exclusive) is entirely defined.
-    pub fn is_range_defined(&self, start: u64, end: u64) -> bool {
+    pub fn is_range_defined(&self, start: Size, end: Size) -> bool {
         if end > self.len {
             return false;
         }
-        for i in start..end {
-            if !self.get(i) {
+        for i in start.bytes()..end.bytes() {
+            if !self.get(Size::from_bytes(i)) {
                 return false;
             }
         }
         true
     }
 
-    pub fn set_range(&mut self, start: u64, end: u64, new_state: bool) {
+    pub fn set_range(&mut self, start: Size, end: Size, new_state: bool) {
         let len = self.len;
         if end > len {
             self.grow(end - len, new_state);
@@ -367,18 +367,18 @@ pub fn set_range(&mut self, start: u64, end: u64, new_state: bool) {
         self.set_range_inbounds(start, end, new_state);
     }
 
-    pub fn set_range_inbounds(&mut self, start: u64, end: u64, new_state: bool) {
-        for i in start..end {
-            self.set(i, new_state);
+    pub fn set_range_inbounds(&mut self, start: Size, end: Size, new_state: bool) {
+        for i in start.bytes()..end.bytes() {
+            self.set(Size::from_bytes(i), new_state);
         }
     }
 
-    pub fn get(&self, i: u64) -> bool {
+    pub fn get(&self, i: Size) -> bool {
         let (block, bit) = bit_index(i);
         (self.blocks[block] & 1 << bit) != 0
     }
 
-    pub fn set(&mut self, i: u64, new_state: bool) {
+    pub fn set(&mut self, i: Size, new_state: bool) {
         let (block, bit) = bit_index(i);
         if new_state {
             self.blocks[block] |= 1 << bit;
@@ -387,10 +387,10 @@ pub fn set(&mut self, i: u64, new_state: bool) {
         }
     }
 
-    pub fn grow(&mut self, amount: u64, new_state: bool) {
-        let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len;
-        if amount > unused_trailing_bits {
-            let additional_blocks = amount / BLOCK_SIZE + 1;
+    pub fn grow(&mut self, amount: Size, new_state: bool) {
+        let unused_trailing_bits = self.blocks.len() as u64 * BLOCK_SIZE - self.len.bytes();
+        if amount.bytes() > unused_trailing_bits {
+            let additional_blocks = amount.bytes() / BLOCK_SIZE + 1;
             assert_eq!(additional_blocks as usize as u64, additional_blocks);
             self.blocks.extend(
                 iter::repeat(0).take(additional_blocks as usize),
@@ -402,7 +402,8 @@ pub fn grow(&mut self, amount: u64, new_state: bool) {
     }
 }
 
-fn bit_index(bits: u64) -> (usize, usize) {
+fn bit_index(bits: Size) -> (usize, usize) {
+    let bits = bits.bytes();
     let a = bits / BLOCK_SIZE;
     let b = bits % BLOCK_SIZE;
     assert_eq!(a as usize as u64, a);
index ad076fe681bee3ce93be156424d3ed638faac5f1..5ac2f7f356ead2947b8951e664281e399a4efe63 100644 (file)
@@ -1,6 +1,6 @@
 #![allow(unknown_lints)]
 
-use ty::layout::{Align, HasDataLayout};
+use ty::layout::{Align, HasDataLayout, Size};
 use ty;
 
 use super::{EvalResult, MemoryPointer, PointerArithmetic, Allocation};
@@ -14,7 +14,7 @@ pub enum ConstValue<'tcx> {
     /// Used only for types with layout::abi::ScalarPair
     ByValPair(PrimVal, PrimVal),
     /// Used only for the remaining cases. An allocation + offset into the allocation
-    ByRef(&'tcx Allocation, u64),
+    ByRef(&'tcx Allocation, Size),
 }
 
 impl<'tcx> ConstValue<'tcx> {
@@ -129,13 +129,13 @@ pub fn signed_offset<C: HasDataLayout>(self, i: i64, cx: C) -> EvalResult<'tcx,
         }
     }
 
-    pub fn offset<C: HasDataLayout>(self, i: u64, cx: C) -> EvalResult<'tcx, Self> {
+    pub fn offset<C: HasDataLayout>(self, i: Size, cx: C) -> EvalResult<'tcx, Self> {
         let layout = cx.data_layout();
         match self.primval {
             PrimVal::Bytes(b) => {
                 assert_eq!(b as u64 as u128, b);
                 Ok(Pointer::from(
-                    PrimVal::Bytes(layout.offset(b as u64, i)? as u128),
+                    PrimVal::Bytes(layout.offset(b as u64, i.bytes())? as u128),
                 ))
             }
             PrimVal::Ptr(ptr) => ptr.offset(i, layout).map(Pointer::from),
@@ -336,25 +336,25 @@ pub fn is_float(self) -> bool {
         }
     }
 
-    pub fn from_uint_size(size: u64) -> Self {
-        match size {
+    pub fn from_uint_size(size: Size) -> Self {
+        match size.bytes() {
             1 => PrimValKind::U8,
             2 => PrimValKind::U16,
             4 => PrimValKind::U32,
             8 => PrimValKind::U64,
             16 => PrimValKind::U128,
-            _ => bug!("can't make uint with size {}", size),
+            _ => bug!("can't make uint with size {}", size.bytes()),
         }
     }
 
-    pub fn from_int_size(size: u64) -> Self {
-        match size {
+    pub fn from_int_size(size: Size) -> Self {
+        match size.bytes() {
             1 => PrimValKind::I8,
             2 => PrimValKind::I16,
             4 => PrimValKind::I32,
             8 => PrimValKind::I64,
             16 => PrimValKind::I128,
-            _ => bug!("can't make int with size {}", size),
+            _ => bug!("can't make int with size {}", size.bytes()),
         }
     }
 
index 40e9b687f0ccc404c479a2cf4c5866c84a0d4775..f42f876510de72be12eb4b013fd0de5482b69142 100644 (file)
@@ -1913,7 +1913,7 @@ pub fn print_miri_value<W: Write>(value: Value, ty: Ty, f: &mut W) -> fmt::Resul
                     .get_alloc(ptr.alloc_id);
                 if let Some(alloc) = alloc {
                     assert_eq!(len as usize as u128, len);
-                    let slice = &alloc.bytes[(ptr.offset as usize)..][..(len as usize)];
+                    let slice = &alloc.bytes[(ptr.offset.bytes() as usize)..][..(len as usize)];
                     let s = ::std::str::from_utf8(slice)
                         .expect("non utf8 str from miri");
                     write!(f, "{:?}", s)
index 9fd2f1bdd7a33bcade7946ad216fc82481c6e287..36c1d335ec4d73ba17ab89698dfc1dc690bfa688 100644 (file)
@@ -16,7 +16,7 @@
 use rustc_data_structures::indexed_vec::Idx;
 use rustc::mir::interpret::{GlobalId, MemoryPointer, PrimVal, Allocation, ConstValue};
 use rustc::ty::{self, Ty};
-use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Scalar};
+use rustc::ty::layout::{self, HasDataLayout, LayoutOf, Scalar, Size};
 use builder::Builder;
 use common::{CodegenCx};
 use common::{C_bytes, C_struct, C_uint_big, C_undef, C_usize};
@@ -68,7 +68,7 @@ pub fn primval_to_llvm(cx: &CodegenCx,
 
                 let llval = unsafe { llvm::LLVMConstInBoundsGEP(
                     consts::bitcast(base_addr, Type::i8p(cx)),
-                    &C_usize(cx, ptr.offset),
+                    &C_usize(cx, ptr.offset.bytes()),
                     1,
                 ) };
                 if scalar.value != layout::Pointer {
@@ -88,6 +88,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
 
     let mut next_offset = 0;
     for (&offset, &alloc_id) in &alloc.relocations {
+        let offset = offset.bytes();
         assert_eq!(offset as usize as u64, offset);
         let offset = offset as usize;
         if offset > next_offset {
@@ -99,7 +100,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx, alloc: &Allocation) -> ValueRef {
         ).expect("const_alloc_to_llvm: could not read relocation pointer") as u64;
         llvals.push(primval_to_llvm(
             cx,
-            PrimVal::Ptr(MemoryPointer { alloc_id, offset: ptr_offset }),
+            PrimVal::Ptr(MemoryPointer { alloc_id, offset: Size::from_bytes(ptr_offset) }),
             &Scalar {
                 value: layout::Primitive::Pointer,
                 valid_range: 0..=!0
@@ -129,7 +130,7 @@ pub fn codegen_static_initializer<'a, 'tcx>(
     let static_ = cx.tcx.const_eval(param_env.and(cid))?;
 
     let alloc = match static_.val {
-        ConstVal::Value(ConstValue::ByRef(alloc, 0)) => alloc,
+        ConstVal::Value(ConstValue::ByRef(alloc, n)) if n.bytes() == 0 => alloc,
         _ => bug!("static const eval returned {:#?}", static_),
     };
     Ok(const_alloc_to_llvm(cx, alloc))
index f6dc81a4706c0351a453861923f50cd531e4c1ef..91e393733341990b2a1ecbe35aecea1942d18570 100644 (file)
@@ -143,7 +143,7 @@ pub fn from_const(bx: &Builder<'a, 'tcx>,
 
                 let llval = unsafe { LLVMConstInBoundsGEP(
                     consts::bitcast(base_addr, Type::i8p(bx.cx)),
-                    &C_usize(bx.cx, offset),
+                    &C_usize(bx.cx, offset.bytes()),
                     1,
                 )};
                 let llval = consts::bitcast(llval, layout.llvm_type(bx.cx).ptr_to());
index b01b3542136c4f230102a6ef130c17a2d8829a36..4739c0e92ed2b79edacff0fe4c845a5bab6eda3a 100644 (file)
@@ -21,7 +21,7 @@
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::middle::region;
 use rustc::infer::InferCtxt;
-use rustc::ty::layout::IntegerExt;
+use rustc::ty::layout::{IntegerExt, Size};
 use rustc::ty::subst::Subst;
 use rustc::ty::{self, Ty, TyCtxt, layout};
 use rustc::ty::subst::Substs;
@@ -182,7 +182,7 @@ pub fn const_eval_literal(
             LitKind::Str(ref s, _) => {
                 let s = s.as_str();
                 let id = self.tcx.allocate_cached(s.as_bytes());
-                let ptr = MemoryPointer::new(id, 0);
+                let ptr = MemoryPointer::new(id, Size::from_bytes(0));
                 ConstValue::ByValPair(
                     PrimVal::Ptr(ptr),
                     PrimVal::from_u128(s.len() as u128),
@@ -190,7 +190,7 @@ pub fn const_eval_literal(
             },
             LitKind::ByteStr(ref data) => {
                 let id = self.tcx.allocate_cached(data);
-                let ptr = MemoryPointer::new(id, 0);
+                let ptr = MemoryPointer::new(id, Size::from_bytes(0));
                 ConstValue::ByVal(PrimVal::Ptr(ptr))
             },
             LitKind::Byte(n) => ConstValue::ByVal(PrimVal::Bytes(n as u128)),
index f930d47dc0bd37e3658f71c8a43bf35eabae4e73..0c2645b4c5cdc4430eb6527a400b23e102a341f2 100644 (file)
@@ -191,7 +191,7 @@ fn lower_byte_str_pattern<'p>(&mut self, pat: &'p Pattern<'tcx>) -> Vec<&'p Patt
                             .interpret_interner
                             .get_alloc(ptr.alloc_id)
                             .unwrap();
-                        assert_eq!(ptr.offset, 0);
+                        assert_eq!(ptr.offset.bytes(), 0);
                         // FIXME: check length
                         alloc.bytes.iter().map(|b| {
                             &*pattern_arena.alloc(Pattern {
index 749e574ff7ad41ca5bfa7420f2ded0f12825491f..0368e6595c18dfecbca16b83d29ff1061d3a3ea3 100644 (file)
@@ -22,6 +22,7 @@
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
 use rustc::mir::interpret::{PrimVal, GlobalId, ConstValue};
 use rustc::ty::{self, TyCtxt, AdtDef, Ty, Region};
+use rustc::ty::layout::Size;
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{Def, CtorKind};
@@ -1083,7 +1084,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
         LitKind::Str(ref s, _) => {
             let s = s.as_str();
             let id = tcx.allocate_cached(s.as_bytes());
-            let ptr = MemoryPointer::new(id, 0);
+            let ptr = MemoryPointer::new(id, Size::from_bytes(0));
             ConstValue::ByValPair(
                 PrimVal::Ptr(ptr),
                 PrimVal::from_u128(s.len() as u128),
@@ -1091,7 +1092,7 @@ fn lit_to_const<'a, 'tcx>(lit: &'tcx ast::LitKind,
         },
         LitKind::ByteStr(ref data) => {
             let id = tcx.allocate_cached(data);
-            let ptr = MemoryPointer::new(id, 0);
+            let ptr = MemoryPointer::new(id, Size::from_bytes(0));
             ConstValue::ByVal(PrimVal::Ptr(ptr))
         },
         LitKind::Byte(n) => ConstValue::ByVal(PrimVal::Bytes(n as u128)),
index 002b5eb187db31ce36c2467687574938bb39b7d2..b5568b833397f210d4d7234565f8e811a2db5381 100644 (file)
@@ -73,7 +73,7 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
         match dest_ty.sty {
             // float -> uint
             TyUint(t) => {
-                let width = t.bit_width().unwrap_or(self.memory.pointer_size() as usize * 8);
+                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bytes() as usize * 8);
                 match fty {
                     FloatTy::F32 => Ok(PrimVal::Bytes(Single::from_bits(bits).to_u128(width).value)),
                     FloatTy::F64 => Ok(PrimVal::Bytes(Double::from_bits(bits).to_u128(width).value)),
@@ -81,7 +81,7 @@ fn cast_from_float(&self, bits: u128, fty: FloatTy, dest_ty: Ty<'tcx>) -> EvalRe
             },
             // float -> int
             TyInt(t) => {
-                let width = t.bit_width().unwrap_or(self.memory.pointer_size() as usize * 8);
+                let width = t.bit_width().unwrap_or(self.memory.pointer_size().bytes() as usize * 8);
                 match fty {
                     FloatTy::F32 => Ok(PrimVal::from_i128(Single::from_bits(bits).to_i128(width).value)),
                     FloatTy::F64 => Ok(PrimVal::from_i128(Double::from_bits(bits).to_i128(width).value)),
index ec696ec82b9d76684ca8529281ae466dc4d08316..c51438170300027e7ec5fbb01ac2216118b2374b 100644 (file)
@@ -114,7 +114,7 @@ pub fn value_to_const_value<'tcx>(
                 let ptr = ptr.primval.to_ptr().unwrap();
                 let alloc = ecx.memory.get(ptr.alloc_id)?;
                 assert!(alloc.align.abi() >= align.abi());
-                assert!(alloc.bytes.len() as u64 - ptr.offset >= layout.size.bytes());
+                assert!(alloc.bytes.len() as u64 - ptr.offset.bytes() >= layout.size.bytes());
                 let mut alloc = alloc.clone();
                 alloc.align = align;
                 let alloc = ecx.tcx.intern_const_alloc(alloc);
@@ -165,7 +165,7 @@ fn eval_body_using_ecx<'a, 'mir, 'tcx>(
     let layout = ecx.layout_of(mir.return_ty().subst(tcx, cid.instance.substs))?;
     assert!(!layout.is_unsized());
     let ptr = ecx.memory.allocate(
-        layout.size.bytes(),
+        layout.size,
         layout.align,
         None,
     )?;
@@ -470,7 +470,7 @@ pub fn const_variant_index<'a, 'tcx>(
     let (ptr, align) = match value {
         Value::ByValPair(..) | Value::ByVal(_) => {
             let layout = ecx.layout_of(ty)?;
-            let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
+            let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?;
             let ptr: Pointer = ptr.into();
             ecx.write_value_to_ptr(value, ptr, layout.align, ty)?;
             (ptr, layout.align)
@@ -487,7 +487,7 @@ pub fn const_value_to_allocation_provider<'a, 'tcx>(
 ) -> &'tcx Allocation {
     match val {
         ConstValue::ByRef(alloc, offset) => {
-            assert_eq!(offset, 0);
+            assert_eq!(offset.bytes(), 0);
             return alloc;
         },
         _ => ()
@@ -500,7 +500,7 @@ pub fn const_value_to_allocation_provider<'a, 'tcx>(
             ());
         let value = ecx.const_value_to_value(val, ty)?;
         let layout = ecx.layout_of(ty)?;
-        let ptr = ecx.memory.allocate(layout.size.bytes(), layout.align, Some(MemoryKind::Stack))?;
+        let ptr = ecx.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))?;
         ecx.write_value_to_ptr(value, ptr.into(), layout.align, ty)?;
         let alloc = ecx.memory.get(ptr.alloc_id)?;
         Ok(tcx.intern_const_alloc(alloc.clone()))
index 7ad507331fa741c18336be21298ae4b448c9a0f2..1b4cdccee76bdc99ec99337c572e0ce7404fedd4 100644 (file)
@@ -207,8 +207,7 @@ pub fn alloc_ptr(&mut self, ty: Ty<'tcx>) -> EvalResult<'tcx, MemoryPointer> {
         let layout = self.layout_of(ty)?;
         assert!(!layout.is_unsized(), "cannot alloc memory for unsized type");
 
-        let size = layout.size.bytes();
-        self.memory.allocate(size, layout.align, Some(MemoryKind::Stack))
+        self.memory.allocate(layout.size, layout.align, Some(MemoryKind::Stack))
     }
 
     pub fn memory(&self) -> &Memory<'a, 'mir, 'tcx, M> {
@@ -598,14 +597,14 @@ pub(super) fn eval_rvalue_into_place(
                         )
                     }
                 };
-                let elem_size = self.layout_of(elem_ty)?.size.bytes();
+                let elem_size = self.layout_of(elem_ty)?.size;
                 let value = self.eval_operand(operand)?.value;
 
                 let (dest, dest_align) = self.force_allocation(dest)?.to_ptr_align();
 
                 // FIXME: speed up repeat filling
                 for i in 0..length {
-                    let elem_dest = dest.offset(i * elem_size, &self)?;
+                    let elem_dest = dest.offset(elem_size * i as u64, &self)?;
                     self.write_value_to_ptr(value, elem_dest, dest_align, elem_ty)?;
                 }
             }
@@ -1027,7 +1026,7 @@ pub fn read_global_as_value(&mut self, gid: GlobalId<'tcx>, ty: Ty<'tcx>) -> Eva
                 .interpret_interner
                 .cache_static(gid.instance.def_id());
             let layout = self.layout_of(ty)?;
-            let ptr = MemoryPointer::new(alloc_id, 0);
+            let ptr = MemoryPointer::new(alloc_id, Size::from_bytes(0));
             return Ok(Value::ByRef(ptr.into(), layout.align))
         }
         let cv = self.const_eval(gid)?;
@@ -1195,7 +1194,7 @@ fn write_value_possibly_by_val<F: FnOnce(&mut Self, Value) -> EvalResult<'tcx>>(
             } else {
                 let dest_ptr = self.alloc_ptr(dest_ty)?.into();
                 let layout = self.layout_of(dest_ty)?;
-                self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size.bytes(), false)?;
+                self.memory.copy(src_ptr, align.min(layout.align), dest_ptr, layout.align, layout.size, false)?;
                 write_dest(self, Value::ByRef(dest_ptr, layout.align))?;
             }
         } else {
@@ -1217,7 +1216,7 @@ pub fn write_value_to_ptr(
         trace!("write_value_to_ptr: {:#?}, {}, {:#?}", value, dest_ty, layout);
         match value {
             Value::ByRef(ptr, align) => {
-                self.memory.copy(ptr, align.min(layout.align), dest, dest_align.min(layout.align), layout.size.bytes(), false)
+                self.memory.copy(ptr, align.min(layout.align), dest, dest_align.min(layout.align), layout.size, false)
             }
             Value::ByVal(primval) => {
                 let signed = match layout.abi {
@@ -1228,7 +1227,7 @@ pub fn write_value_to_ptr(
                     _ if primval.is_undef() => false,
                     _ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout)
                 };
-                self.memory.write_primval(dest, dest_align, primval, layout.size.bytes(), signed)
+                self.memory.write_primval(dest, dest_align, primval, layout.size, signed)
             }
             Value::ByValPair(a_val, b_val) => {
                 trace!("write_value_to_ptr valpair: {:#?}", layout);
@@ -1239,10 +1238,10 @@ pub fn write_value_to_ptr(
                 let (a_size, b_size) = (a.size(&self), b.size(&self));
                 let a_ptr = dest;
                 let b_offset = a_size.abi_align(b.align(&self));
-                let b_ptr = dest.offset(b_offset.bytes(), &self)?.into();
+                let b_ptr = dest.offset(b_offset, &self)?.into();
                 // TODO: What about signedess?
-                self.memory.write_primval(a_ptr, dest_align, a_val, a_size.bytes(), false)?;
-                self.memory.write_primval(b_ptr, dest_align, b_val, b_size.bytes(), false)
+                self.memory.write_primval(a_ptr, dest_align, a_val, a_size, false)?;
+                self.memory.write_primval(b_ptr, dest_align, b_val, b_size, false)
             }
         }
     }
@@ -1257,11 +1256,11 @@ pub fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimValKind>
             ty::TyInt(int_ty) => {
                 use syntax::ast::IntTy::*;
                 let size = match int_ty {
-                    I8 => 1,
-                    I16 => 2,
-                    I32 => 4,
-                    I64 => 8,
-                    I128 => 16,
+                    I8 => Size::from_bytes(1),
+                    I16 => Size::from_bytes(2),
+                    I32 => Size::from_bytes(4),
+                    I64 => Size::from_bytes(8),
+                    I128 => Size::from_bytes(16),
                     Isize => self.memory.pointer_size(),
                 };
                 PrimValKind::from_int_size(size)
@@ -1270,11 +1269,11 @@ pub fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimValKind>
             ty::TyUint(uint_ty) => {
                 use syntax::ast::UintTy::*;
                 let size = match uint_ty {
-                    U8 => 1,
-                    U16 => 2,
-                    U32 => 4,
-                    U64 => 8,
-                    U128 => 16,
+                    U8 => Size::from_bytes(1),
+                    U16 => Size::from_bytes(2),
+                    U32 => Size::from_bytes(4),
+                    U64 => Size::from_bytes(8),
+                    U128 => Size::from_bytes(16),
                     Usize => self.memory.pointer_size(),
                 };
                 PrimValKind::from_uint_size(size)
@@ -1297,8 +1296,8 @@ pub fn ty_to_primval_kind(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimValKind>
                     layout::Abi::Scalar(ref scalar) => {
                         use rustc::ty::layout::Primitive::*;
                         match scalar.value {
-                            Int(i, false) => PrimValKind::from_uint_size(i.size().bytes()),
-                            Int(i, true) => PrimValKind::from_int_size(i.size().bytes()),
+                            Int(i, false) => PrimValKind::from_uint_size(i.size()),
+                            Int(i, true) => PrimValKind::from_int_size(i.size()),
                             F32 => PrimValKind::F32,
                             F64 => PrimValKind::F64,
                             Pointer => PrimValKind::Ptr,
@@ -1372,7 +1371,7 @@ pub fn validate_ptr_target(
     ) -> EvalResult<'tcx> {
         match ty.sty {
             ty::TyBool => {
-                let val = self.memory.read_primval(ptr, ptr_align, 1)?;
+                let val = self.memory.read_primval(ptr, ptr_align, Size::from_bytes(1))?;
                 match val {
                     PrimVal::Bytes(0) | PrimVal::Bytes(1) => (),
                     // TODO: This seems a little overeager, should reading at bool type already be insta-UB?
@@ -1380,7 +1379,7 @@ pub fn validate_ptr_target(
                 }
             }
             ty::TyChar => {
-                let c = self.memory.read_primval(ptr, ptr_align, 4)?.to_bytes()? as u32;
+                let c = self.memory.read_primval(ptr, ptr_align, Size::from_bytes(4))?.to_bytes()? as u32;
                 match ::std::char::from_u32(c) {
                     Some(..) => (),
                     None => return err!(InvalidChar(c as u128)),
@@ -1402,7 +1401,7 @@ pub fn validate_ptr_target(
                 }
 
                 if let layout::Abi::Scalar(ref scalar) = self.layout_of(ty)?.abi {
-                    let size = scalar.value.size(self).bytes();
+                    let size = scalar.value.size(self);
                     self.memory.read_primval(ptr, ptr_align, size)?;
                 }
             }
@@ -1437,7 +1436,7 @@ pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> Ev
 
         match layout.abi {
             layout::Abi::Scalar(..) => {
-                let primval = self.memory.read_primval(ptr, ptr_align, layout.size.bytes())?;
+                let primval = self.memory.read_primval(ptr, ptr_align, layout.size)?;
                 Ok(Some(Value::ByVal(primval)))
             }
             layout::Abi::ScalarPair(ref a, ref b) => {
@@ -1445,9 +1444,9 @@ pub fn try_read_value(&self, ptr: Pointer, ptr_align: Align, ty: Ty<'tcx>) -> Ev
                 let (a_size, b_size) = (a.size(self), b.size(self));
                 let a_ptr = ptr;
                 let b_offset = a_size.abi_align(b.align(self));
-                let b_ptr = ptr.offset(b_offset.bytes(), self)?.into();
-                let a_val = self.memory.read_primval(a_ptr, ptr_align, a_size.bytes())?;
-                let b_val = self.memory.read_primval(b_ptr, ptr_align, b_size.bytes())?;
+                let b_ptr = ptr.offset(b_offset, self)?.into();
+                let a_val = self.memory.read_primval(a_ptr, ptr_align, a_size)?;
+                let b_val = self.memory.read_primval(b_ptr, ptr_align, b_size)?;
                 Ok(Some(Value::ByValPair(a_val, b_val)))
             }
             _ => Ok(None),
index 5af0a053e9239e5b57aafa709f2c0803134fd0de..a5c94e4fcecfc2316bd6296e18c707679e9f6380 100644 (file)
@@ -7,6 +7,7 @@
 
 use rustc::mir;
 use rustc::ty::{self, Ty};
+use rustc::ty::layout::Size;
 use syntax::codemap::Span;
 use syntax::ast::Mutability;
 
@@ -92,7 +93,7 @@ fn global_item_with_linkage<'a>(
     fn check_locks<'a>(
         _mem: &Memory<'a, 'mir, 'tcx, Self>,
         _ptr: MemoryPointer,
-        _size: u64,
+        _size: Size,
         _access: AccessKind,
     ) -> EvalResult<'tcx> {
         Ok(())
index ba1c05deef1b42e8a0264c5ef4d7dc34223d14ce..755eaa443b6cddd8324c366b78022b0cb76c0256 100644 (file)
@@ -5,7 +5,7 @@
 use rustc::ty::Instance;
 use rustc::ty::ParamEnv;
 use rustc::ty::maps::TyCtxtAt;
-use rustc::ty::layout::{self, Align, TargetDataLayout};
+use rustc::ty::layout::{self, Align, TargetDataLayout, Size};
 use syntax::ast::Mutability;
 use rustc::middle::const_val::{ConstVal, ErrKind};
 
@@ -73,12 +73,12 @@ pub fn allocations<'x>(
 
     pub fn create_fn_alloc(&mut self, instance: Instance<'tcx>) -> MemoryPointer {
         let id = self.tcx.interpret_interner.create_fn_alloc(instance);
-        MemoryPointer::new(id, 0)
+        MemoryPointer::new(id, Size::from_bytes(0))
     }
 
     pub fn allocate_cached(&mut self, bytes: &[u8]) -> MemoryPointer {
         let id = self.tcx.allocate_cached(bytes);
-        MemoryPointer::new(id, 0)
+        MemoryPointer::new(id, Size::from_bytes(0))
     }
 
     /// kind is `None` for statics
@@ -105,24 +105,24 @@ pub fn allocate_value(
     /// kind is `None` for statics
     pub fn allocate(
         &mut self,
-        size: u64,
+        size: Size,
         align: Align,
         kind: Option<MemoryKind<M::MemoryKinds>>,
     ) -> EvalResult<'tcx, MemoryPointer> {
         let id = self.allocate_value(Allocation::undef(size, align), kind)?;
-        Ok(MemoryPointer::new(id, 0))
+        Ok(MemoryPointer::new(id, Size::from_bytes(0)))
     }
 
     pub fn reallocate(
         &mut self,
         ptr: MemoryPointer,
-        old_size: u64,
+        old_size: Size,
         old_align: Align,
-        new_size: u64,
+        new_size: Size,
         new_align: Align,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx, MemoryPointer> {
-        if ptr.offset != 0 {
+        if ptr.offset.bytes() != 0 {
             return err!(ReallocateNonBasePtr);
         }
         if self.alloc_map.contains_key(&ptr.alloc_id) {
@@ -163,10 +163,10 @@ pub fn deallocate_local(&mut self, ptr: MemoryPointer) -> EvalResult<'tcx> {
     pub fn deallocate(
         &mut self,
         ptr: MemoryPointer,
-        size_and_align: Option<(u64, Align)>,
+        size_and_align: Option<(Size, Align)>,
         kind: MemoryKind<M::MemoryKinds>,
     ) -> EvalResult<'tcx> {
-        if ptr.offset != 0 {
+        if ptr.offset.bytes() != 0 {
             return err!(DeallocateNonBasePtr);
         }
 
@@ -208,8 +208,8 @@ pub fn deallocate(
             ));
         }
         if let Some((size, align)) = size_and_align {
-            if size != alloc.bytes.len() as u64 || align != alloc.align {
-                return err!(IncorrectAllocationInformation(size, alloc.bytes.len(), align.abi(), alloc.align.abi()));
+            if size.bytes() != alloc.bytes.len() as u64 || align != alloc.align {
+                return err!(IncorrectAllocationInformation(size, Size::from_bytes(alloc.bytes.len() as u64), align, alloc.align));
             }
         }
 
@@ -218,8 +218,8 @@ pub fn deallocate(
         Ok(())
     }
 
-    pub fn pointer_size(&self) -> u64 {
-        self.tcx.data_layout.pointer_size.bytes()
+    pub fn pointer_size(&self) -> Size {
+        self.tcx.data_layout.pointer_size
     }
 
     pub fn endianness(&self) -> layout::Endian {
@@ -232,10 +232,10 @@ pub fn check_align(&self, ptr: Pointer, required_align: Align) -> EvalResult<'tc
         let (offset, alloc_align) = match ptr.into_inner_primval() {
             PrimVal::Ptr(ptr) => {
                 let alloc = self.get(ptr.alloc_id)?;
-                (ptr.offset, alloc.align)
+                (ptr.offset.bytes(), alloc.align)
             }
             PrimVal::Bytes(bytes) => {
-                let v = ((bytes as u128) % (1 << self.pointer_size())) as u64;
+                let v = ((bytes as u128) % (1 << self.pointer_size().bytes())) as u64;
                 if v == 0 {
                     return err!(InvalidNullPointerUsage);
                 }
@@ -247,16 +247,17 @@ pub fn check_align(&self, ptr: Pointer, required_align: Align) -> EvalResult<'tc
         // Check alignment
         if alloc_align.abi() < required_align.abi() {
             return err!(AlignmentCheckFailed {
-                has: alloc_align.abi(),
-                required: required_align.abi(),
+                has: alloc_align,
+                required: required_align,
             });
         }
         if offset % required_align.abi() == 0 {
             Ok(())
         } else {
+            let has = offset % required_align.abi();
             err!(AlignmentCheckFailed {
-                has: offset % required_align.abi(),
-                required: required_align.abi(),
+                has: Align::from_bytes(has, has).unwrap(),
+                required: required_align,
             })
         }
     }
@@ -264,11 +265,11 @@ pub fn check_align(&self, ptr: Pointer, required_align: Align) -> EvalResult<'tc
     pub fn check_bounds(&self, ptr: MemoryPointer, access: bool) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         let allocation_size = alloc.bytes.len() as u64;
-        if ptr.offset > allocation_size {
+        if ptr.offset.bytes() > allocation_size {
             return err!(PointerOutOfBounds {
                 ptr,
                 access,
-                allocation_size,
+                allocation_size: Size::from_bytes(allocation_size),
             });
         }
         Ok(())
@@ -354,7 +355,7 @@ fn get_mut(
     }
 
     pub fn get_fn(&self, ptr: MemoryPointer) -> EvalResult<'tcx, Instance<'tcx>> {
-        if ptr.offset != 0 {
+        if ptr.offset.bytes() != 0 {
             return err!(InvalidFunctionPointer);
         }
         debug!("reading fn ptr: {}", ptr.alloc_id);
@@ -419,15 +420,16 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
                 };
 
             for i in 0..(alloc.bytes.len() as u64) {
+                let i = Size::from_bytes(i);
                 if let Some(&target_id) = alloc.relocations.get(&i) {
                     if allocs_seen.insert(target_id) {
                         allocs_to_print.push_back(target_id);
                     }
                     relocations.push((i, target_id));
                 }
-                if alloc.undef_mask.is_range_defined(i, i + 1) {
+                if alloc.undef_mask.is_range_defined(i, i + Size::from_bytes(1)) {
                     // this `as usize` is fine, since `i` came from a `usize`
-                    write!(msg, "{:02x} ", alloc.bytes[i as usize]).unwrap();
+                    write!(msg, "{:02x} ", alloc.bytes[i.bytes() as usize]).unwrap();
                 } else {
                     msg.push_str("__ ");
                 }
@@ -444,11 +446,11 @@ pub fn dump_allocs(&self, mut allocs: Vec<AllocId>) {
             if !relocations.is_empty() {
                 msg.clear();
                 write!(msg, "{:1$}", "", prefix_len).unwrap(); // Print spaces.
-                let mut pos = 0;
-                let relocation_width = (self.pointer_size() - 1) * 3;
+                let mut pos = Size::from_bytes(0);
+                let relocation_width = (self.pointer_size().bytes() - 1) * 3;
                 for (i, target_id) in relocations {
                     // this `as usize` is fine, since we can't print more chars than `usize::MAX`
-                    write!(msg, "{:1$}", "", ((i - pos) * 3) as usize).unwrap();
+                    write!(msg, "{:1$}", "", ((i - pos) * 3).bytes() as usize).unwrap();
                     let target = format!("({})", target_id);
                     // this `as usize` is fine, since we can't print more chars than `usize::MAX`
                     write!(msg, "â””{0:─^1$}┘ ", target, relocation_width as usize).unwrap();
@@ -476,45 +478,45 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     fn get_bytes_unchecked(
         &self,
         ptr: MemoryPointer,
-        size: u64,
+        size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &[u8]> {
         // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
         self.check_align(ptr.into(), align)?;
-        if size == 0 {
+        if size.bytes() == 0 {
             return Ok(&[]);
         }
         M::check_locks(self, ptr, size, AccessKind::Read)?;
         self.check_bounds(ptr.offset(size, self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
         let alloc = self.get(ptr.alloc_id)?;
-        assert_eq!(ptr.offset as usize as u64, ptr.offset);
-        assert_eq!(size as usize as u64, size);
-        let offset = ptr.offset as usize;
-        Ok(&alloc.bytes[offset..offset + size as usize])
+        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
+        let offset = ptr.offset.bytes() as usize;
+        Ok(&alloc.bytes[offset..offset + size.bytes() as usize])
     }
 
     fn get_bytes_unchecked_mut(
         &mut self,
         ptr: MemoryPointer,
-        size: u64,
+        size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &mut [u8]> {
         // Zero-sized accesses can use dangling pointers, but they still have to be aligned and non-NULL
         self.check_align(ptr.into(), align)?;
-        if size == 0 {
+        if size.bytes() == 0 {
             return Ok(&mut []);
         }
         M::check_locks(self, ptr, size, AccessKind::Write)?;
         self.check_bounds(ptr.offset(size, &*self)?, true)?; // if ptr.offset is in bounds, then so is ptr (because offset checks for overflow)
         let alloc = self.get_mut(ptr.alloc_id)?;
-        assert_eq!(ptr.offset as usize as u64, ptr.offset);
-        assert_eq!(size as usize as u64, size);
-        let offset = ptr.offset as usize;
-        Ok(&mut alloc.bytes[offset..offset + size as usize])
+        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
+        let offset = ptr.offset.bytes() as usize;
+        Ok(&mut alloc.bytes[offset..offset + size.bytes() as usize])
     }
 
-    fn get_bytes(&self, ptr: MemoryPointer, size: u64, align: Align) -> EvalResult<'tcx, &[u8]> {
-        assert_ne!(size, 0);
+    fn get_bytes(&self, ptr: MemoryPointer, size: Size, align: Align) -> EvalResult<'tcx, &[u8]> {
+        assert_ne!(size.bytes(), 0);
         if self.relocations(ptr, size)?.count() != 0 {
             return err!(ReadPointerAsBytes);
         }
@@ -525,10 +527,10 @@ fn get_bytes(&self, ptr: MemoryPointer, size: u64, align: Align) -> EvalResult<'
     fn get_bytes_mut(
         &mut self,
         ptr: MemoryPointer,
-        size: u64,
+        size: Size,
         align: Align,
     ) -> EvalResult<'tcx, &mut [u8]> {
-        assert_ne!(size, 0);
+        assert_ne!(size.bytes(), 0);
         self.clear_relocations(ptr, size)?;
         self.mark_definedness(ptr.into(), size, true)?;
         self.get_bytes_unchecked_mut(ptr, size, align)
@@ -594,13 +596,13 @@ pub fn copy(
         src_align: Align,
         dest: Pointer,
         dest_align: Align,
-        size: u64,
+        size: Size,
         nonoverlapping: bool,
     ) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be aligned
         self.check_align(src, src_align)?;
         self.check_align(dest, dest_align)?;
-        if size == 0 {
+        if size.bytes() == 0 {
             return Ok(());
         }
         let src = src.to_ptr()?;
@@ -625,7 +627,7 @@ pub fn copy(
         // behind `src` and `dest`. Also, we use the overlapping-safe `ptr::copy` if `src` and
         // `dest` could possibly overlap.
         unsafe {
-            assert_eq!(size as usize as u64, size);
+            assert_eq!(size.bytes() as usize as u64, size.bytes());
             if src.alloc_id == dest.alloc_id {
                 if nonoverlapping {
                     if (src.offset <= dest.offset && src.offset + size > dest.offset) ||
@@ -636,9 +638,9 @@ pub fn copy(
                         ));
                     }
                 }
-                ptr::copy(src_bytes, dest_bytes, size as usize);
+                ptr::copy(src_bytes, dest_bytes, size.bytes() as usize);
             } else {
-                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size as usize);
+                ptr::copy_nonoverlapping(src_bytes, dest_bytes, size.bytes() as usize);
             }
         }
 
@@ -651,26 +653,27 @@ pub fn copy(
 
     pub fn read_c_str(&self, ptr: MemoryPointer) -> EvalResult<'tcx, &[u8]> {
         let alloc = self.get(ptr.alloc_id)?;
-        assert_eq!(ptr.offset as usize as u64, ptr.offset);
-        let offset = ptr.offset as usize;
+        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
+        let offset = ptr.offset.bytes() as usize;
         match alloc.bytes[offset..].iter().position(|&c| c == 0) {
             Some(size) => {
-                if self.relocations(ptr, (size + 1) as u64)?.count() != 0 {
+                let p1 = Size::from_bytes((size + 1) as u64);
+                if self.relocations(ptr, p1)?.count() != 0 {
                     return err!(ReadPointerAsBytes);
                 }
-                self.check_defined(ptr, (size + 1) as u64)?;
-                M::check_locks(self, ptr, (size + 1) as u64, AccessKind::Read)?;
+                self.check_defined(ptr, p1)?;
+                M::check_locks(self, ptr, p1, AccessKind::Read)?;
                 Ok(&alloc.bytes[offset..offset + size])
             }
             None => err!(UnterminatedCString(ptr)),
         }
     }
 
-    pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> {
+    pub fn read_bytes(&self, ptr: Pointer, size: Size) -> EvalResult<'tcx, &[u8]> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         self.check_align(ptr, align)?;
-        if size == 0 {
+        if size.bytes() == 0 {
             return Ok(&[]);
         }
         self.get_bytes(ptr.to_ptr()?, size, align)
@@ -683,16 +686,16 @@ pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> {
         if src.is_empty() {
             return Ok(());
         }
-        let bytes = self.get_bytes_mut(ptr.to_ptr()?, src.len() as u64, align)?;
+        let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?;
         bytes.clone_from_slice(src);
         Ok(())
     }
 
-    pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> {
+    pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: Size) -> EvalResult<'tcx> {
         // Empty accesses don't need to be valid pointers, but they should still be non-NULL
         let align = Align::from_bytes(1, 1).unwrap();
         self.check_align(ptr, align)?;
-        if count == 0 {
+        if count.bytes() == 0 {
             return Ok(());
         }
         let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?;
@@ -702,7 +705,7 @@ pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<
         Ok(())
     }
 
-    pub fn read_primval(&self, ptr: MemoryPointer, ptr_align: Align, size: u64) -> EvalResult<'tcx, PrimVal> {
+    pub fn read_primval(&self, ptr: MemoryPointer, ptr_align: Align, size: Size) -> EvalResult<'tcx, PrimVal> {
         self.check_relocation_edges(ptr, size)?; // Make sure we don't read part of a pointer as a pointer
         let endianness = self.endianness();
         let bytes = self.get_bytes_unchecked(ptr, size, ptr_align.min(self.int_align(size)))?;
@@ -721,7 +724,7 @@ pub fn read_primval(&self, ptr: MemoryPointer, ptr_align: Align, size: u64) -> E
         } else {
             let alloc = self.get(ptr.alloc_id)?;
             match alloc.relocations.get(&ptr.offset) {
-                Some(&alloc_id) => return Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, bytes as u64))),
+                Some(&alloc_id) => return Ok(PrimVal::Ptr(MemoryPointer::new(alloc_id, Size::from_bytes(bytes as u64)))),
                 None => {},
             }
         }
@@ -733,13 +736,13 @@ pub fn read_ptr_sized(&self, ptr: MemoryPointer, ptr_align: Align) -> EvalResult
         self.read_primval(ptr, ptr_align, self.pointer_size())
     }
 
-    pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: PrimVal, size: u64, signed: bool) -> EvalResult<'tcx> {
+    pub fn write_primval(&mut self, ptr: Pointer, ptr_align: Align, val: PrimVal, size: Size, signed: bool) -> EvalResult<'tcx> {
         let endianness = self.endianness();
 
         let bytes = match val {
             PrimVal::Ptr(val) => {
                 assert_eq!(size, self.pointer_size());
-                val.offset as u128
+                val.offset.bytes() as u128
             }
 
             PrimVal::Bytes(bytes) => bytes,
@@ -782,16 +785,16 @@ pub fn write_ptr_sized_unsigned(&mut self, ptr: MemoryPointer, ptr_align: Align,
         self.write_primval(ptr.into(), ptr_align, val, ptr_size, false)
     }
 
-    fn int_align(&self, size: u64) -> Align {
+    fn int_align(&self, size: Size) -> Align {
         // We assume pointer-sized integers have the same alignment as pointers.
         // We also assume signed and unsigned integers of the same size have the same alignment.
-        let ity = match size {
+        let ity = match size.bytes() {
             1 => layout::I8,
             2 => layout::I16,
             4 => layout::I32,
             8 => layout::I64,
             16 => layout::I128,
-            _ => bug!("bad integer size: {}", size),
+            _ => bug!("bad integer size: {}", size.bytes()),
         };
         ity.align(self)
     }
@@ -802,14 +805,14 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
     fn relocations(
         &self,
         ptr: MemoryPointer,
-        size: u64,
-    ) -> EvalResult<'tcx, btree_map::Range<u64, AllocId>> {
-        let start = ptr.offset.saturating_sub(self.pointer_size() - 1);
+        size: Size,
+    ) -> EvalResult<'tcx, btree_map::Range<Size, AllocId>> {
+        let start = ptr.offset.bytes().saturating_sub(self.pointer_size().bytes() - 1);
         let end = ptr.offset + size;
-        Ok(self.get(ptr.alloc_id)?.relocations.range(start..end))
+        Ok(self.get(ptr.alloc_id)?.relocations.range(Size::from_bytes(start)..end))
     }
 
-    fn clear_relocations(&mut self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx> {
+    fn clear_relocations(&mut self, ptr: MemoryPointer, size: Size) -> EvalResult<'tcx> {
         // Find all relocations overlapping the given range.
         let keys: Vec<_> = self.relocations(ptr, size)?.map(|(&k, _)| k).collect();
         if keys.is_empty() {
@@ -841,9 +844,9 @@ fn clear_relocations(&mut self, ptr: MemoryPointer, size: u64) -> EvalResult<'tc
         Ok(())
     }
 
-    fn check_relocation_edges(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx> {
-        let overlapping_start = self.relocations(ptr, 0)?.count();
-        let overlapping_end = self.relocations(ptr.offset(size, self)?, 0)?.count();
+    fn check_relocation_edges(&self, ptr: MemoryPointer, size: Size) -> EvalResult<'tcx> {
+        let overlapping_start = self.relocations(ptr, Size::from_bytes(0))?.count();
+        let overlapping_end = self.relocations(ptr.offset(size, self)?, Size::from_bytes(0))?.count();
         if overlapping_start + overlapping_end != 0 {
             return err!(ReadPointerAsBytes);
         }
@@ -858,26 +861,26 @@ fn copy_undef_mask(
         &mut self,
         src: MemoryPointer,
         dest: MemoryPointer,
-        size: u64,
+        size: Size,
     ) -> EvalResult<'tcx> {
         // The bits have to be saved locally before writing to dest in case src and dest overlap.
-        assert_eq!(size as usize as u64, size);
-        let mut v = Vec::with_capacity(size as usize);
-        for i in 0..size {
-            let defined = self.get(src.alloc_id)?.undef_mask.get(src.offset + i);
+        assert_eq!(size.bytes() as usize as u64, size.bytes());
+        let mut v = Vec::with_capacity(size.bytes() as usize);
+        for i in 0..size.bytes() {
+            let defined = self.get(src.alloc_id)?.undef_mask.get(src.offset + Size::from_bytes(i));
             v.push(defined);
         }
         for (i, defined) in v.into_iter().enumerate() {
             self.get_mut(dest.alloc_id)?.undef_mask.set(
                 dest.offset +
-                    i as u64,
+                    Size::from_bytes(i as u64),
                 defined,
             );
         }
         Ok(())
     }
 
-    fn check_defined(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx> {
+    fn check_defined(&self, ptr: MemoryPointer, size: Size) -> EvalResult<'tcx> {
         let alloc = self.get(ptr.alloc_id)?;
         if !alloc.undef_mask.is_range_defined(
             ptr.offset,
@@ -892,10 +895,10 @@ fn check_defined(&self, ptr: MemoryPointer, size: u64) -> EvalResult<'tcx> {
     pub fn mark_definedness(
         &mut self,
         ptr: Pointer,
-        size: u64,
+        size: Size,
         new_state: bool,
     ) -> EvalResult<'tcx> {
-        if size == 0 {
+        if size.bytes() == 0 {
             return Ok(());
         }
         let ptr = ptr.to_ptr()?;
index 883b17b8584fb010ff322449d6262a5e4cced110..6ccbcf07370b0eb76f8c3a83e4b737fe57f8b653 100644 (file)
@@ -1,6 +1,6 @@
 use rustc::mir;
 use rustc::ty::{self, Ty, TyCtxt};
-use rustc::ty::layout::{self, Align, LayoutOf, TyLayout};
+use rustc::ty::layout::{self, Align, LayoutOf, TyLayout, Size};
 use rustc_data_structures::indexed_vec::Idx;
 
 use rustc::mir::interpret::{GlobalId, Value, PrimVal, EvalResult, Pointer, MemoryPointer};
@@ -210,7 +210,7 @@ pub fn eval_place(&mut self, mir_place: &mir::Place<'tcx>) -> EvalResult<'tcx, P
                 };
                 let alloc = Machine::init_static(self, cid)?;
                 Place::Ptr {
-                    ptr: MemoryPointer::new(alloc, 0).into(),
+                    ptr: MemoryPointer::new(alloc, Size::from_bytes(0)).into(),
                     align: layout.align,
                     extra: PlaceExtra::None,
                 }
@@ -267,9 +267,9 @@ pub fn place_field(
                     base_layout.ty,
                     base_ptr.to_value_with_vtable(tab),
                 )?;
-                offset.abi_align(align).bytes()
+                offset.abi_align(align)
             }
-            _ => offset.bytes(),
+            _ => offset,
         };
 
         let ptr = base_ptr.offset(offset, &self)?;
@@ -325,14 +325,14 @@ pub fn place_index(
         let (base_ptr, align) = base.to_ptr_align();
 
         let (elem_ty, len) = base.elem_ty_and_len(outer_ty, self.tcx.tcx);
-        let elem_size = self.layout_of(elem_ty)?.size.bytes();
+        let elem_size = self.layout_of(elem_ty)?.size;
         assert!(
             n < len,
             "Tried to access element {} of array/slice with length {}",
             n,
             len
         );
-        let ptr = base_ptr.offset(n * elem_size, &*self)?;
+        let ptr = base_ptr.offset(elem_size * n, &*self)?;
         Ok(Place::Ptr {
             ptr,
             align,
@@ -401,7 +401,7 @@ pub fn eval_place_projection(
                 let (base_ptr, align) = base.to_ptr_align();
 
                 let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
-                let elem_size = self.layout_of(elem_ty)?.size.bytes();
+                let elem_size = self.layout_of(elem_ty)?.size;
                 assert!(n >= min_length as u64);
 
                 let index = if from_end {
@@ -410,7 +410,7 @@ pub fn eval_place_projection(
                     u64::from(offset)
                 };
 
-                let ptr = base_ptr.offset(index * elem_size, &self)?;
+                let ptr = base_ptr.offset(elem_size * index, &self)?;
                 Ok(Place::Ptr { ptr, align, extra: PlaceExtra::None })
             }
 
@@ -420,9 +420,9 @@ pub fn eval_place_projection(
                 let (base_ptr, align) = base.to_ptr_align();
 
                 let (elem_ty, n) = base.elem_ty_and_len(base_ty, self.tcx.tcx);
-                let elem_size = self.layout_of(elem_ty)?.size.bytes();
+                let elem_size = self.layout_of(elem_ty)?.size;
                 assert!(u64::from(from) <= n - u64::from(to));
-                let ptr = base_ptr.offset(u64::from(from) * elem_size, &self)?;
+                let ptr = base_ptr.offset(elem_size * u64::from(from), &self)?;
                 // sublicing arrays produces arrays
                 let extra = if self.type_is_sized(base_ty) {
                     PlaceExtra::None
index c61487f106b66f272f2440ea367a63cfb4e9da91..c5b823ca87b526cbf2968e2147317470d9e703dc 100644 (file)
@@ -341,7 +341,7 @@ fn eval_fn_call(
                                     Value::ByRef(ptr, align) => {
                                         for (i, arg_local) in arg_locals.enumerate() {
                                             let field = layout.field(&self, i)?;
-                                            let offset = layout.fields.offset(i).bytes();
+                                            let offset = layout.fields.offset(i);
                                             let arg = Value::ByRef(ptr.offset(offset, &self)?,
                                                                    align.min(field.align));
                                             let dest =
index 6cd8e267ec5c114e43742f85195061ca18655901..2075400d04f5105cf752f01e9ee8143961b16c5a 100644 (file)
@@ -221,7 +221,7 @@ pub enum Endian {
 }
 
 /// Size of a type in bytes.
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
+#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub struct Size {
     raw: u64
 }