diff --git a/src/bin/miri.rs b/src/bin/miri.rs index d2a9bc6087e..96caa54468b 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -53,7 +53,7 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { NestedMetaItemKind::MetaItem(ref inner) => match inner.node { MetaItemKind::NameValue(ref name, ref value) => { match &**name { - "memory_size" => memory_size = extract_int(value) as usize, + "memory_size" => memory_size = extract_int(value), "step_limit" => step_limit = extract_int(value), "stack_limit" => stack_limit = extract_int(value) as usize, _ => state.session.span_err(item.span, "unknown miri attribute"), diff --git a/src/error.rs b/src/error.rs index 65cbcc97015..afc1855e8e7 100644 --- a/src/error.rs +++ b/src/error.rs @@ -18,8 +18,8 @@ pub enum EvalError<'tcx> { InvalidDiscriminant, PointerOutOfBounds { ptr: Pointer, - size: usize, - allocation_size: usize, + size: u64, + allocation_size: u64, }, ReadPointerAsBytes, InvalidPointerMath, @@ -32,15 +32,15 @@ pub enum EvalError<'tcx> { Math(Span, ConstMathErr), InvalidChar(u64), OutOfMemory { - allocation_size: usize, - memory_size: usize, - memory_usage: usize, + allocation_size: u64, + memory_size: u64, + memory_usage: u64, }, ExecutionTimeLimitReached, StackFrameLimitReached, AlignmentCheckFailed { - required: usize, - has: usize, + required: u64, + has: u64, }, CalledClosureAsFunction, VtableForArgumentlessMethod, diff --git a/src/interpreter/cast.rs b/src/interpreter/cast.rs index 217a10a4c7b..5bf5d26c228 100644 --- a/src/interpreter/cast.rs +++ b/src/interpreter/cast.rs @@ -67,7 +67,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { TyChar if v as u8 as u64 == v => Ok(PrimVal::new(v, Char)), TyChar => Err(EvalError::InvalidChar(v)), - TyRawPtr(_) => Ok(PrimVal::from_ptr(Pointer::from_int(v as usize))), + TyRawPtr(_) => Ok(PrimVal::from_ptr(Pointer::from_int(v))), _ => Err(EvalError::Unimplemented(format!("int to {:?} cast", ty))), } diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index d61ba4ee3f7..abeea0790b8 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -167,7 +167,7 @@ pub enum StackPopCleanup { } impl<'a, 'tcx> EvalContext<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, memory_size: usize, stack_limit: usize, step_limit: u64) -> Self { + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, memory_size: u64, stack_limit: usize, step_limit: u64) -> Self { EvalContext { tcx: tcx, memory: Memory::new(&tcx.data_layout, memory_size), @@ -211,7 +211,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> { // FIXME: cache these allocs - let ptr = self.memory.allocate(s.len(), 1)?; + let ptr = self.memory.allocate(s.len() as u64, 1)?; self.memory.write_bytes(ptr, s.as_bytes())?; self.memory.freeze(ptr.alloc_id)?; Ok(Value::ByValPair(PrimVal::from_ptr(ptr), self.usize_primval(s.len() as u64))) @@ -255,7 +255,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Str(ref s) => return self.str_to_value(s), ByteStr(ref bs) => { - let ptr = self.memory.allocate(bs.len(), 1)?; + let ptr = self.memory.allocate(bs.len() as u64, 1)?; self.memory.write_bytes(ptr, bs)?; self.memory.freeze(ptr.alloc_id)?; PrimVal::from_ptr(ptr) @@ -292,25 +292,25 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.tcx.normalize_associated_type(&substituted) } - fn type_size(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, Option> { + fn type_size(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, Option> { self.type_size_with_substs(ty, self.substs()) } - fn type_align(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, usize> { + fn type_align(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, u64> { self.type_align_with_substs(ty, self.substs()) } - fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, Option> { + fn type_size_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, Option> { let layout = self.type_layout_with_substs(ty, substs)?; if layout.is_unsized() { Ok(None) } else { - Ok(Some(layout.size(&self.tcx.data_layout).bytes() as usize)) + Ok(Some(layout.size(&self.tcx.data_layout).bytes())) } } - fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, usize> { - self.type_layout_with_substs(ty, substs).map(|layout| layout.align(&self.tcx.data_layout).abi() as usize) + fn type_align_with_substs(&self, ty: Ty<'tcx>, substs: &'tcx Substs<'tcx>) -> EvalResult<'tcx, u64> { + self.type_layout_with_substs(ty, substs).map(|layout| layout.align(&self.tcx.data_layout).abi()) } fn type_layout(&self, ty: Ty<'tcx>) -> EvalResult<'tcx, &'tcx Layout> { @@ -464,7 +464,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { for (offset, operand) in offsets.into_iter().zip(operands) { let value = self.eval_operand(operand)?; let value_ty = self.operand_ty(operand); - let field_dest = dest.offset(offset as isize); + let field_dest = dest.offset(offset); self.write_value_to_ptr(value, field_dest, value_ty)?; } Ok(()) @@ -525,8 +525,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { General { discr, ref variants, .. } => { if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { let discr_val = adt_def.variants[variant].disr_val.to_u64_unchecked(); - let discr_size = discr.size().bytes() as usize; - let discr_offset = variants[variant].offsets[0].bytes() as isize; + let discr_size = discr.size().bytes(); + let discr_offset = variants[variant].offsets[0].bytes(); // FIXME(solson) let dest = self.force_allocation(dest)?; @@ -581,7 +581,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // FIXME(solson) let dest = self.force_allocation(dest)?.to_ptr(); - let dest = dest.offset(offset.bytes() as isize); + let dest = dest.offset(offset.bytes()); let dest_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield"); try!(self.memory.write_int(dest, 0, dest_size)); } @@ -594,7 +594,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { assert_eq!(operands.len(), 0); if let mir::AggregateKind::Adt(adt_def, variant, _, _) = *kind { let n = adt_def.variants[variant].disr_val.to_u64_unchecked(); - let size = discr.size().bytes() as usize; + let size = discr.size().bytes(); let val = if signed { PrimVal::from_int_with_size(n as i64, size) @@ -621,10 +621,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Repeat(ref operand, _) => { let (elem_ty, length) = match dest_ty.sty { - ty::TyArray(elem_ty, n) => (elem_ty, n), + ty::TyArray(elem_ty, n) => (elem_ty, n as u64), _ => bug!("tried to assign array-repeat to non-array type {:?}", dest_ty), }; - self.inc_step_counter_and_check_limit(length as u64)?; + self.inc_step_counter_and_check_limit(length)?; let elem_size = self.type_size(elem_ty)?.expect("repeat element type must be sized"); let value = self.eval_operand(operand)?; @@ -632,7 +632,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let dest = self.force_allocation(dest)?.to_ptr(); for i in 0..length { - let elem_dest = dest.offset((i * elem_size) as isize); + let elem_dest = dest.offset(i * elem_size); self.write_value_to_ptr(value, elem_dest, elem_ty)?; } } @@ -741,15 +741,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } fn nonnull_offset_and_ty(&self, ty: Ty<'tcx>, nndiscr: u64, discrfield: &[u32]) -> EvalResult<'tcx, (Size, Ty<'tcx>)> { - // Skip the constant 0 at the start meant for LLVM GEP. - let mut path = discrfield.iter().skip(1).map(|&i| i as usize); + // Skip the constant 0 at the start meant for LLVM GEP and the outer non-null variant + let path = discrfield.iter().skip(2).map(|&i| i as usize); // Handle the field index for the outer non-null variant. let inner_ty = match ty.sty { ty::TyAdt(adt_def, substs) => { let variant = &adt_def.variants[nndiscr as usize]; - let index = path.next().unwrap(); - let field = &variant.fields[index]; + let index = discrfield[1]; + let field = &variant.fields[index as usize]; field.ty(self.tcx, substs) } _ => bug!("non-enum for StructWrappedNullablePointer: {}", ty), @@ -804,8 +804,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(variant.offsets[field_index]) } FatPointer { .. } => { - let bytes = field_index * self.memory.pointer_size(); - Ok(Size::from_bytes(bytes as u64)) + let bytes = field_index as u64 * self.memory.pointer_size(); + Ok(Size::from_bytes(bytes)) } _ => { let msg = format!("can't handle type: {:?}, with layout: {:?}", ty, layout); @@ -980,7 +980,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { _ => bug!("field access on non-product type: {:?}", base_layout), }; - let ptr = base_ptr.offset(offset.bytes() as isize); + let ptr = base_ptr.offset(offset.bytes()); let extra = if self.type_is_sized(field_ty) { LvalueExtra::None } else { @@ -1048,7 +1048,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let n = self.value_to_primval(n_ptr, usize)? .expect_uint("Projection::Index expected usize"); assert!(n < len); - let ptr = base_ptr.offset(n as isize * elem_size as isize); + let ptr = base_ptr.offset(n * elem_size); (ptr, LvalueExtra::None) } @@ -1062,12 +1062,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { assert!(n >= min_length as u64); let index = if from_end { - n as isize - offset as isize + n - u64::from(offset) } else { - offset as isize + u64::from(offset) }; - let ptr = base_ptr.offset(index * elem_size as isize); + let ptr = base_ptr.offset(index * elem_size); (ptr, LvalueExtra::None) } @@ -1078,9 +1078,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (elem_ty, n) = base.elem_ty_and_len(base_ty); let elem_size = self.type_size(elem_ty)?.expect("slice element must be sized"); - assert!((from as u64) <= n - (to as u64)); - let ptr = base_ptr.offset(from as isize * elem_size as isize); - let extra = LvalueExtra::Length(n - to as u64 - from as u64); + assert!(u64::from(from) <= n - u64::from(to)); + let ptr = base_ptr.offset(u64::from(from) * elem_size); + let extra = LvalueExtra::Length(n - u64::from(to) - u64::from(from)); (ptr, extra) } }; @@ -1318,8 +1318,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty: Ty<'tcx> ) -> EvalResult<'tcx, ()> { assert_eq!(self.get_field_count(ty)?, 2); - let field_0 = self.get_field_offset(ty, 0)?.bytes() as isize; - let field_1 = self.get_field_offset(ty, 1)?.bytes() as isize; + let field_0 = self.get_field_offset(ty, 0)?.bytes(); + let field_1 = self.get_field_offset(ty, 1)?.bytes(); self.memory.write_primval(ptr.offset(field_0), a)?; self.memory.write_primval(ptr.offset(field_1), b)?; Ok(()) @@ -1368,7 +1368,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyAdt(..) => { use rustc::ty::layout::Layout::*; if let CEnum { discr, signed, .. } = *self.type_layout(ty)? { - let size = discr.size().bytes() as usize; + let size = discr.size().bytes(); if signed { PrimValKind::from_int_size(size) } else { @@ -1450,7 +1450,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { PrimVal::from_ptr(p) } else { trace!("reading fat pointer extra of type {}", ty); - let extra = ptr.offset(self.memory.pointer_size() as isize); + let extra = ptr.offset(self.memory.pointer_size()); let extra = match self.tcx.struct_tail(ty).sty { ty::TyTrait(..) => PrimVal::from_ptr(self.memory.read_ptr(extra)?), ty::TySlice(..) | @@ -1464,7 +1464,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyAdt(..) => { use rustc::ty::layout::Layout::*; if let CEnum { discr, signed, .. } = *self.type_layout(ty)? { - let size = discr.size().bytes() as usize; + let size = discr.size().bytes(); if signed { let n = self.memory.read_int(ptr, size)?; PrimVal::from_int_with_size(n, size) @@ -1566,8 +1566,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { if self.type_size(dst_fty)? == Some(0) { continue; } - let src_field_offset = self.get_field_offset(src_ty, i)?.bytes() as isize; - let dst_field_offset = self.get_field_offset(dest_ty, i)?.bytes() as isize; + let src_field_offset = self.get_field_offset(src_ty, i)?.bytes(); + let dst_field_offset = self.get_field_offset(dest_ty, i)?.bytes(); let src_f_ptr = src_ptr.offset(src_field_offset); let dst_f_ptr = dest.offset(dst_field_offset); if src_fty == dst_fty { @@ -1699,7 +1699,7 @@ impl<'tcx> Lvalue<'tcx> { pub fn eval_main<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, - memory_size: usize, + memory_size: u64, step_limit: u64, stack_limit: usize, ) { diff --git a/src/interpreter/terminator/intrinsics.rs b/src/interpreter/terminator/intrinsics.rs index 013bacc30d2..87a9229aba0 100644 --- a/src/interpreter/terminator/intrinsics.rs +++ b/src/interpreter/terminator/intrinsics.rs @@ -46,7 +46,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = arg_vals[0].read_ptr(&self.memory)?; let offset = self.value_to_primval(arg_vals[1], isize)? .expect_int("arith_offset second arg not isize"); - let new_ptr = ptr.offset(offset as isize); + let new_ptr = ptr.signed_offset(offset); self.write_primval(dest, PrimVal::from_ptr(new_ptr))?; } @@ -150,7 +150,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let dest = arg_vals[1].read_ptr(&self.memory)?; let count = self.value_to_primval(arg_vals[2], usize)? .expect_uint("arith_offset second arg not isize"); - self.memory.copy(src, dest, count as usize * elem_size, elem_align)?; + self.memory.copy(src, dest, count * elem_size, elem_align)?; } "ctpop" | @@ -220,7 +220,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "forget" => {} "init" => { - let size = dest_layout.size(&self.tcx.data_layout).bytes() as usize; + let size = dest_layout.size(&self.tcx.data_layout).bytes(); let init = |this: &mut Self, val: Option| { match val { Some(Value::ByRef(ptr)) => { @@ -280,12 +280,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "offset" => { let pointee_ty = substs.type_at(0); - let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as isize; + // FIXME: assuming here that type size is < i64::max_value() + let pointee_size = self.type_size(pointee_ty)?.expect("cannot offset a pointer to an unsized type") as i64; let offset = self.value_to_primval(arg_vals[1], isize)? .expect_int("offset second arg not isize"); let ptr = arg_vals[0].read_ptr(&self.memory)?; - let result_ptr = ptr.offset(offset as isize * pointee_size); + let result_ptr = ptr.signed_offset(offset * pointee_size); self.write_primval(dest, PrimVal::from_ptr(result_ptr))?; } @@ -378,7 +379,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "uninit" => { - let size = dest_layout.size(&self.tcx.data_layout).bytes() as usize; + let size = dest_layout.size(&self.tcx.data_layout).bytes(); let uninit = |this: &mut Self, val: Option| { match val { Some(Value::ByRef(ptr)) => { @@ -482,8 +483,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { ty::TyTrait(..) => { let (_, vtable) = value.expect_ptr_vtable_pair(&self.memory)?; // the second entry in the vtable is the dynamic size of the object. - let size = self.memory.read_usize(vtable.offset(pointer_size as isize))?; - let align = self.memory.read_usize(vtable.offset(pointer_size as isize * 2))?; + let size = self.memory.read_usize(vtable.offset(pointer_size))?; + let align = self.memory.read_usize(vtable.offset(pointer_size * 2))?; Ok((size, align)) } diff --git a/src/interpreter/terminator/mod.rs b/src/interpreter/terminator/mod.rs index ad0e139e6e1..ab5b695ff1d 100644 --- a/src/interpreter/terminator/mod.rs +++ b/src/interpreter/terminator/mod.rs @@ -254,23 +254,23 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let discr_val = match *adt_layout { General { discr, .. } | CEnum { discr, signed: false, .. } => { let discr_size = discr.size().bytes(); - self.memory.read_uint(adt_ptr, discr_size as usize)? + self.memory.read_uint(adt_ptr, discr_size)? } CEnum { discr, signed: true, .. } => { let discr_size = discr.size().bytes(); - self.memory.read_int(adt_ptr, discr_size as usize)? as u64 + self.memory.read_int(adt_ptr, discr_size)? as u64 } RawNullablePointer { nndiscr, value } => { - let discr_size = value.size(&self.tcx.data_layout).bytes() as usize; + let discr_size = value.size(&self.tcx.data_layout).bytes(); trace!("rawnullablepointer with size {}", discr_size); self.read_nonnull_discriminant_value(adt_ptr, nndiscr, discr_size)? } StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => { let (offset, ty) = self.nonnull_offset_and_ty(adt_ty, nndiscr, discrfield)?; - let nonnull = adt_ptr.offset(offset.bytes() as isize); + let nonnull = adt_ptr.offset(offset.bytes()); trace!("struct wrapped nullable pointer type: {}", ty); // only the pointer part of a fat pointer is used for this space optimization let discr_size = self.type_size(ty)?.expect("bad StructWrappedNullablePointer discrfield"); @@ -285,7 +285,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Ok(discr_val) } - fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64, discr_size: usize) -> EvalResult<'tcx, u64> { + fn read_nonnull_discriminant_value(&self, ptr: Pointer, nndiscr: u64, discr_size: u64) -> EvalResult<'tcx, u64> { let not_null = match self.memory.read_uint(ptr, discr_size) { Ok(0) => false, Ok(_) | Err(EvalError::ReadPointerAsBytes) => true, @@ -300,7 +300,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { def_id: DefId, args: &[mir::Operand<'tcx>], dest: Lvalue<'tcx>, - dest_size: usize, + dest_size: u64, ) -> EvalResult<'tcx, ()> { let name = self.tcx.item_name(def_id); let attrs = self.tcx.get_attrs(def_id); @@ -327,7 +327,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { .expect_uint("__rust_allocate first arg not usize"); let align = self.value_to_primval(args[1], usize)? .expect_uint("__rust_allocate second arg not usize"); - let ptr = self.memory.allocate(size as usize, align as usize)?; + let ptr = self.memory.allocate(size, align)?; self.write_primval(dest, PrimVal::from_ptr(ptr))?; } @@ -345,14 +345,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let ptr = args[0].read_ptr(&self.memory)?; let size = self.value_to_primval(args[2], usize)?.expect_uint("__rust_reallocate third arg not usize"); let align = self.value_to_primval(args[3], usize)?.expect_uint("__rust_reallocate fourth arg not usize"); - let new_ptr = self.memory.reallocate(ptr, size as usize, align as usize)?; + let new_ptr = self.memory.reallocate(ptr, size, align)?; self.write_primval(dest, PrimVal::from_ptr(new_ptr))?; } "memcmp" => { let left = args[0].read_ptr(&self.memory)?; let right = args[1].read_ptr(&self.memory)?; - let n = self.value_to_primval(args[2], usize)?.expect_uint("__rust_reallocate first arg not usize") as usize; + let n = self.value_to_primval(args[2], usize)?.expect_uint("__rust_reallocate first arg not usize"); let result = { let left_bytes = self.memory.read_bytes(left, n)?; @@ -414,7 +414,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { _ => bug!("rust-call ABI tuple argument wasn't Value::ByRef"), }; for (offset, ty) in offsets.zip(fields) { - let arg = Value::ByRef(last_ptr.offset(offset as isize)); + let arg = Value::ByRef(last_ptr.offset(offset)); args.push((arg, ty)); } } @@ -496,13 +496,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } traits::VtableObject(ref data) => { - let idx = self.tcx.get_vtable_index_of_object_method(data, def_id); + let idx = self.tcx.get_vtable_index_of_object_method(data, def_id) as u64; if let Some(&mut(ref mut first_arg, ref mut first_ty)) = args.get_mut(0) { let (self_ptr, vtable) = first_arg.expect_ptr_vtable_pair(&self.memory)?; *first_arg = Value::ByVal(PrimVal::from_ptr(self_ptr)); let idx = idx + 3; let offset = idx * self.memory.pointer_size(); - let fn_ptr = self.memory.read_ptr(vtable.offset(offset as isize))?; + let fn_ptr = self.memory.read_ptr(vtable.offset(offset))?; let (def_id, substs, _abi, sig) = self.memory.get_fn(fn_ptr.alloc_id)?; *first_ty = sig.inputs[0]; Ok((def_id, substs)) @@ -600,6 +600,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Layout::StructWrappedNullablePointer { nndiscr, ref nonnull, .. } => { let discr = self.read_discriminant_value(adt_ptr, ty)?; if discr == nndiscr { + assert_eq!(discr as usize as u64, discr); adt_def.variants[discr as usize].fields.iter().zip(&nonnull.offsets) } else { // FIXME: the zst variant might contain zst types that impl Drop @@ -609,6 +610,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Layout::RawNullablePointer { nndiscr, .. } => { let discr = self.read_discriminant_value(adt_ptr, ty)?; if discr == nndiscr { + assert_eq!(discr as usize as u64, discr); assert_eq!(adt_def.variants[discr as usize].fields.len(), 1); let field_ty = &adt_def.variants[discr as usize].fields[0]; let field_ty = monomorphize_field_ty(self.tcx, field_ty, substs); @@ -656,10 +658,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }, ty::TySlice(elem_ty) => { let (ptr, len) = match lval { - Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => (ptr, len as isize), + Lvalue::Ptr { ptr, extra: LvalueExtra::Length(len) } => (ptr, len), _ => bug!("expected an lvalue with a length"), }; - let size = self.type_size(elem_ty)?.expect("slice element must be sized") as isize; + let size = self.type_size(elem_ty)?.expect("slice element must be sized"); // FIXME: this creates a lot of stack frames if the element type has // a drop impl for i in 0..len { @@ -672,11 +674,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { Lvalue::Ptr { ptr, extra } => (ptr, extra), _ => bug!("expected an lvalue with optional extra data"), }; - let size = self.type_size(elem_ty)?.expect("array element cannot be unsized") as isize; + let size = self.type_size(elem_ty)?.expect("array element cannot be unsized"); // FIXME: this creates a lot of stack frames if the element type has // a drop impl - for i in 0..len { - self.drop(Lvalue::Ptr { ptr: ptr.offset(i as isize * size), extra: extra }, elem_ty, drop)?; + for i in 0..(len as u64) { + self.drop(Lvalue::Ptr { ptr: ptr.offset(i * size), extra: extra }, elem_ty, drop)?; } }, // FIXME: what about TyClosure and TyAnon? @@ -699,7 +701,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let (adt_ptr, extra) = self.force_allocation(lval)?.to_ptr_and_extra(); // manual iteration, because we need to be careful about the last field if it is unsized while let Some((field_ty, offset)) = fields.next() { - let ptr = adt_ptr.offset(offset.bytes() as isize); + let ptr = adt_ptr.offset(offset.bytes()); if self.type_is_sized(field_ty) { self.drop(Lvalue::from_ptr(ptr), field_ty, drop)?; } else { diff --git a/src/interpreter/value.rs b/src/interpreter/value.rs index fa89d02ad77..f31f1ca24bc 100644 --- a/src/interpreter/value.rs +++ b/src/interpreter/value.rs @@ -34,7 +34,7 @@ impl<'a, 'tcx: 'a> Value { match *self { ByRef(ref_ptr) => { let ptr = mem.read_ptr(ref_ptr)?; - let vtable = mem.read_ptr(ref_ptr.offset(mem.pointer_size() as isize))?; + let vtable = mem.read_ptr(ref_ptr.offset(mem.pointer_size()))?; Ok((ptr, vtable)) } @@ -49,7 +49,7 @@ impl<'a, 'tcx: 'a> Value { match *self { ByRef(ref_ptr) => { let ptr = mem.read_ptr(ref_ptr)?; - let len = mem.read_usize(ref_ptr.offset(mem.pointer_size() as isize))?; + let len = mem.read_usize(ref_ptr.offset(mem.pointer_size()))?; Ok((ptr, len)) }, ByValPair(ptr, val) => { diff --git a/src/interpreter/vtable.rs b/src/interpreter/vtable.rs index 920e57a1f34..89db8e111e4 100644 --- a/src/interpreter/vtable.rs +++ b/src/interpreter/vtable.rs @@ -84,7 +84,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { let align = self.type_align(trait_ref.self_ty())?; let ptr_size = self.memory.pointer_size(); - let vtable = self.memory.allocate(ptr_size * (3 + methods.len()), ptr_size)?; + let vtable = self.memory.allocate(ptr_size * (3 + methods.len() as u64), ptr_size)?; // in case there is no drop function to be called, this still needs to be initialized self.memory.write_usize(vtable, 0)?; @@ -99,12 +99,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - self.memory.write_usize(vtable.offset(ptr_size as isize), size as u64)?; - self.memory.write_usize(vtable.offset((ptr_size * 2) as isize), align as u64)?; + self.memory.write_usize(vtable.offset(ptr_size), size)?; + self.memory.write_usize(vtable.offset((ptr_size * 2)), align)?; for (i, method) in methods.into_iter().enumerate() { if let Some(method) = method { - self.memory.write_ptr(vtable.offset(ptr_size as isize * (3 + i as isize)), method)?; + self.memory.write_ptr(vtable.offset(ptr_size * (3 + i as u64)), method)?; } } diff --git a/src/memory.rs b/src/memory.rs index af10ce4352c..c4c045c121b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -33,11 +33,11 @@ pub struct Allocation { pub bytes: Vec, /// Maps from byte addresses to allocations. /// Only the first byte of a pointer is inserted into the map. - pub relocations: BTreeMap, + pub relocations: BTreeMap, /// Denotes undefined memory. Reading from undefined memory is forbidden in miri pub undef_mask: UndefMask, /// The alignment of the allocation to detect unaligned reads. - pub align: usize, + pub align: u64, /// Whether the allocation may be modified. /// Use the `freeze` method of `Memory` to ensure that an error occurs, if the memory of this /// allocation is modified in the future. @@ -47,24 +47,35 @@ pub struct Allocation { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct Pointer { pub alloc_id: AllocId, - pub offset: usize, + pub offset: u64, } impl Pointer { - pub fn new(alloc_id: AllocId, offset: usize) -> Self { + pub fn new(alloc_id: AllocId, offset: u64) -> Self { Pointer { alloc_id: alloc_id, offset: offset } } - pub fn offset(self, i: isize) -> Self { - let new_offset = (self.offset as isize + i) as usize; - Pointer::new(self.alloc_id, new_offset) + pub fn signed_offset(self, i: i64) -> Self { + // FIXME: is it possible to over/underflow here? + if i < 0 { + // trickery to ensure that i64::min_value() works fine + // this formula only works for true negative values, it panics for zero! + let n = u64::max_value() - (i as u64) + 1; + Pointer::new(self.alloc_id, self.offset - n) + } else { + self.offset(i as u64) + } + } + + pub fn offset(self, i: u64) -> Self { + Pointer::new(self.alloc_id, self.offset + i) } pub fn points_to_zst(&self) -> bool { self.alloc_id == ZST_ALLOC_ID } - pub fn to_int<'tcx>(&self) -> EvalResult<'tcx, usize> { + pub fn to_int<'tcx>(&self) -> EvalResult<'tcx, u64> { match self.alloc_id { NEVER_ALLOC_ID | ZST_ALLOC_ID => Ok(self.offset), @@ -72,9 +83,7 @@ impl Pointer { } } - // FIXME(solson): Integer pointers should use u64, not usize. Target pointers can be larger - // than host usize. - pub fn from_int(i: usize) -> Self { + pub fn from_int(i: u64) -> Self { Pointer::new(NEVER_ALLOC_ID, i) } @@ -103,9 +112,9 @@ pub struct Memory<'a, 'tcx> { /// Actual memory allocations (arbitrary bytes, may contain pointers into other allocations) alloc_map: HashMap, /// Number of virtual bytes allocated - memory_usage: usize, + memory_usage: u64, /// Maximum number of virtual bytes that may be allocated - memory_size: usize, + memory_size: u64, /// Function "allocations". They exist solely so pointers have something to point to, and /// we can figure out what they point to. functions: HashMap>, @@ -119,7 +128,7 @@ const ZST_ALLOC_ID: AllocId = AllocId(0); const NEVER_ALLOC_ID: AllocId = AllocId(1); impl<'a, 'tcx> Memory<'a, 'tcx> { - pub fn new(layout: &'a TargetDataLayout, max_memory: usize) -> Self { + pub fn new(layout: &'a TargetDataLayout, max_memory: u64) -> Self { Memory { alloc_map: HashMap::new(), functions: HashMap::new(), @@ -175,7 +184,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Pointer::new(id, 0) } - pub fn allocate(&mut self, size: usize, align: usize) -> EvalResult<'tcx, Pointer> { + pub fn allocate(&mut self, size: u64, align: u64) -> EvalResult<'tcx, Pointer> { if size == 0 { return Ok(Pointer::zst_ptr()); } @@ -189,8 +198,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { }); } self.memory_usage += size; + assert_eq!(size as usize as u64, size); let alloc = Allocation { - bytes: vec![0; size], + bytes: vec![0; size as usize], relocations: BTreeMap::new(), undef_mask: UndefMask::new(size), align: align, @@ -204,7 +214,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { // TODO(solson): Track which allocations were returned from __rust_allocate and report an error // when reallocating/deallocating any others. - pub fn reallocate(&mut self, ptr: Pointer, new_size: usize, align: usize) -> EvalResult<'tcx, Pointer> { + pub fn reallocate(&mut self, ptr: Pointer, new_size: u64, align: u64) -> EvalResult<'tcx, Pointer> { // TODO(solson): Report error about non-__rust_allocate'd pointer. if ptr.offset != 0 { return Err(EvalError::Unimplemented(format!("bad pointer offset: {}", ptr.offset))); @@ -216,19 +226,21 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { return Err(EvalError::ReallocatedFrozenMemory); } - let size = self.get(ptr.alloc_id)?.bytes.len(); + let size = self.get(ptr.alloc_id)?.bytes.len() as u64; if new_size > size { let amount = new_size - size; self.memory_usage += amount; let alloc = self.get_mut(ptr.alloc_id)?; - alloc.bytes.extend(iter::repeat(0).take(amount)); + assert_eq!(amount as usize as u64, amount); + alloc.bytes.extend(iter::repeat(0).take(amount as usize)); alloc.undef_mask.grow(amount, false); } else if size > new_size { self.memory_usage -= size - new_size; - self.clear_relocations(ptr.offset(new_size as isize), size - new_size)?; + self.clear_relocations(ptr.offset(new_size), size - new_size)?; let alloc = self.get_mut(ptr.alloc_id)?; - alloc.bytes.truncate(new_size); + // `as usize` is fine here, since it is smaller than `size`, which came from a usize + alloc.bytes.truncate(new_size as usize); alloc.bytes.shrink_to_fit(); alloc.undef_mask.truncate(new_size); } @@ -250,7 +262,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } if let Some(alloc) = self.alloc_map.remove(&ptr.alloc_id) { - self.memory_usage -= alloc.bytes.len(); + self.memory_usage -= alloc.bytes.len() as u64; } else { debug!("deallocated a pointer twice: {}", ptr.alloc_id); // TODO(solson): Report error about erroneous free. This is blocked on properly tracking @@ -262,15 +274,15 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - pub fn pointer_size(&self) -> usize { - self.layout.pointer_size.bytes() as usize + pub fn pointer_size(&self) -> u64 { + self.layout.pointer_size.bytes() } pub fn endianess(&self) -> layout::Endian { self.layout.endian } - pub fn check_align(&self, ptr: Pointer, align: usize) -> EvalResult<'tcx, ()> { + pub fn check_align(&self, ptr: Pointer, align: u64) -> EvalResult<'tcx, ()> { let alloc = self.get(ptr.alloc_id)?; if alloc.align < align { return Err(EvalError::AlignmentCheckFailed { @@ -358,7 +370,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { (Some(_), Some(_)) => bug!("miri invariant broken: an allocation id exists that points to both a function and a memory location"), }; - for i in 0..alloc.bytes.len() { + for i in 0..(alloc.bytes.len() as u64) { if let Some(&target_id) = alloc.relocations.get(&i) { if !allocs_seen.contains(&target_id) { allocs_to_print.push_back(target_id); @@ -366,7 +378,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { relocations.push((i, target_id)); } if alloc.undef_mask.is_range_defined(i, i + 1) { - write!(msg, "{:02x} ", alloc.bytes[i]).unwrap(); + // this `as usize` is fine, since `i` came from a `usize` + write!(msg, "{:02x} ", alloc.bytes[i as usize]).unwrap(); } else { msg.push_str("__ "); } @@ -381,13 +394,15 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { let mut pos = 0; let relocation_width = (self.pointer_size() - 1) * 3; for (i, target_id) in relocations { - write!(msg, "{:1$}", "", (i - pos) * 3).unwrap(); + // this `as usize` is fine, since we can't print more chars than `usize::MAX` + write!(msg, "{:1$}", "", ((i - pos) * 3) as usize).unwrap(); let target = match target_id { ZST_ALLOC_ID => String::from("zst"), NEVER_ALLOC_ID => String::from("int ptr"), _ => format!("({})", target_id), }; - write!(msg, "└{0:─^1$}┘ ", target, relocation_width).unwrap(); + // 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(); pos = i + self.pointer_size(); } trace!("{}", msg); @@ -398,37 +413,43 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { /// Byte accessors impl<'a, 'tcx> Memory<'a, 'tcx> { - fn get_bytes_unchecked(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, &[u8]> { + fn get_bytes_unchecked(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> { if size == 0 { return Ok(&[]); } let alloc = self.get(ptr.alloc_id)?; - if ptr.offset + size > alloc.bytes.len() { + if ptr.offset + size > alloc.bytes.len() as u64 { return Err(EvalError::PointerOutOfBounds { ptr: ptr, size: size, - allocation_size: alloc.bytes.len(), + allocation_size: alloc.bytes.len() as u64, }); } - Ok(&alloc.bytes[ptr.offset..ptr.offset + size]) + 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]) } - fn get_bytes_unchecked_mut(&mut self, ptr: Pointer, size: usize) -> EvalResult<'tcx, &mut [u8]> { + fn get_bytes_unchecked_mut(&mut self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &mut [u8]> { if size == 0 { return Ok(&mut []); } let alloc = self.get_mut(ptr.alloc_id)?; - if ptr.offset + size > alloc.bytes.len() { + if ptr.offset + size > alloc.bytes.len() as u64 { return Err(EvalError::PointerOutOfBounds { ptr: ptr, size: size, - allocation_size: alloc.bytes.len(), + allocation_size: alloc.bytes.len() as u64, }); } - Ok(&mut alloc.bytes[ptr.offset..ptr.offset + size]) + 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]) } - fn get_bytes(&self, ptr: Pointer, size: usize, align: usize) -> EvalResult<'tcx, &[u8]> { + fn get_bytes(&self, ptr: Pointer, size: u64, align: u64) -> EvalResult<'tcx, &[u8]> { if size == 0 { return Ok(&[]); } @@ -440,7 +461,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { self.get_bytes_unchecked(ptr, size) } - fn get_bytes_mut(&mut self, ptr: Pointer, size: usize, align: usize) -> EvalResult<'tcx, &mut [u8]> { + fn get_bytes_mut(&mut self, ptr: Pointer, size: u64, align: u64) -> EvalResult<'tcx, &mut [u8]> { if size == 0 { return Ok(&mut []); } @@ -476,7 +497,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - pub fn copy(&mut self, src: Pointer, dest: Pointer, size: usize, align: usize) -> EvalResult<'tcx, ()> { + pub fn copy(&mut self, src: Pointer, dest: Pointer, size: u64, align: u64) -> EvalResult<'tcx, ()> { if size == 0 { return Ok(()); } @@ -489,10 +510,11 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { // 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); if src.alloc_id == dest.alloc_id { - ptr::copy(src_bytes, dest_bytes, size); + ptr::copy(src_bytes, dest_bytes, size as usize); } else { - ptr::copy_nonoverlapping(src_bytes, dest_bytes, size); + ptr::copy_nonoverlapping(src_bytes, dest_bytes, size as usize); } } @@ -502,17 +524,17 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - pub fn read_bytes(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, &[u8]> { + pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> { self.get_bytes(ptr, size, 1) } pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx, ()> { - let bytes = self.get_bytes_mut(ptr, src.len(), 1)?; + let bytes = self.get_bytes_mut(ptr, src.len() as u64, 1)?; bytes.clone_from_slice(src); Ok(()) } - pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: usize) -> EvalResult<'tcx, ()> { + pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx, ()> { let bytes = self.get_bytes_mut(ptr, count, 1)?; for b in bytes { *b = val; } Ok(()) @@ -523,7 +545,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { self.check_defined(ptr, size)?; let endianess = self.endianess(); let bytes = self.get_bytes_unchecked(ptr, size)?; - let offset = read_target_uint(endianess, bytes).unwrap() as usize; + let offset = read_target_uint(endianess, bytes).unwrap(); let alloc = self.get(ptr.alloc_id)?; match alloc.relocations.get(&ptr.offset) { Some(&alloc_id) => Ok(Pointer::new(alloc_id, offset)), @@ -539,7 +561,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn write_primval(&mut self, dest: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> { if let Some(alloc_id) = val.relocation { - return self.write_ptr(dest, Pointer::new(alloc_id, val.bits as usize)); + return self.write_ptr(dest, Pointer::new(alloc_id, val.bits)); } use primval::PrimValKind::*; @@ -556,7 +578,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn read_bool(&self, ptr: Pointer) -> EvalResult<'tcx, bool> { - let bytes = self.get_bytes(ptr, 1, self.layout.i1_align.abi() as usize)?; + let bytes = self.get_bytes(ptr, 1, self.layout.i1_align.abi())?; match bytes[0] { 0 => Ok(false), 1 => Ok(true), @@ -565,27 +587,27 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn write_bool(&mut self, ptr: Pointer, b: bool) -> EvalResult<'tcx, ()> { - let align = self.layout.i1_align.abi() as usize; + let align = self.layout.i1_align.abi(); self.get_bytes_mut(ptr, 1, align) .map(|bytes| bytes[0] = b as u8) } - fn int_align(&self, size: usize) -> EvalResult<'tcx, usize> { + fn int_align(&self, size: u64) -> EvalResult<'tcx, u64> { match size { - 1 => Ok(self.layout.i8_align.abi() as usize), - 2 => Ok(self.layout.i16_align.abi() as usize), - 4 => Ok(self.layout.i32_align.abi() as usize), - 8 => Ok(self.layout.i64_align.abi() as usize), + 1 => Ok(self.layout.i8_align.abi()), + 2 => Ok(self.layout.i16_align.abi()), + 4 => Ok(self.layout.i32_align.abi()), + 8 => Ok(self.layout.i64_align.abi()), _ => bug!("bad integer size: {}", size), } } - pub fn read_int(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, i64> { + pub fn read_int(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, i64> { let align = self.int_align(size)?; self.get_bytes(ptr, size, align).map(|b| read_target_int(self.endianess(), b).unwrap()) } - pub fn write_int(&mut self, ptr: Pointer, n: i64, size: usize) -> EvalResult<'tcx, ()> { + pub fn write_int(&mut self, ptr: Pointer, n: i64, size: u64) -> EvalResult<'tcx, ()> { let align = self.int_align(size)?; let endianess = self.endianess(); let b = self.get_bytes_mut(ptr, size, align)?; @@ -593,12 +615,12 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - pub fn read_uint(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, u64> { + pub fn read_uint(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, u64> { let align = self.int_align(size)?; self.get_bytes(ptr, size, align).map(|b| read_target_uint(self.endianess(), b).unwrap()) } - pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: usize) -> EvalResult<'tcx, ()> { + pub fn write_uint(&mut self, ptr: Pointer, n: u64, size: u64) -> EvalResult<'tcx, ()> { let align = self.int_align(size)?; let endianess = self.endianess(); let b = self.get_bytes_mut(ptr, size, align)?; @@ -626,7 +648,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn write_f32(&mut self, ptr: Pointer, f: f32) -> EvalResult<'tcx, ()> { let endianess = self.endianess(); - let align = self.layout.f32_align.abi() as usize; + let align = self.layout.f32_align.abi(); let b = self.get_bytes_mut(ptr, 4, align)?; write_target_f32(endianess, b, f).unwrap(); Ok(()) @@ -634,34 +656,34 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn write_f64(&mut self, ptr: Pointer, f: f64) -> EvalResult<'tcx, ()> { let endianess = self.endianess(); - let align = self.layout.f64_align.abi() as usize; + let align = self.layout.f64_align.abi(); let b = self.get_bytes_mut(ptr, 8, align)?; write_target_f64(endianess, b, f).unwrap(); Ok(()) } pub fn read_f32(&self, ptr: Pointer) -> EvalResult<'tcx, f32> { - self.get_bytes(ptr, 4, self.layout.f32_align.abi() as usize) + self.get_bytes(ptr, 4, self.layout.f32_align.abi()) .map(|b| read_target_f32(self.endianess(), b).unwrap()) } pub fn read_f64(&self, ptr: Pointer) -> EvalResult<'tcx, f64> { - self.get_bytes(ptr, 8, self.layout.f64_align.abi() as usize) + self.get_bytes(ptr, 8, self.layout.f64_align.abi()) .map(|b| read_target_f64(self.endianess(), b).unwrap()) } } /// Relocations impl<'a, 'tcx> Memory<'a, 'tcx> { - fn relocations(&self, ptr: Pointer, size: usize) - -> EvalResult<'tcx, btree_map::Range> + fn relocations(&self, ptr: Pointer, size: u64) + -> EvalResult<'tcx, btree_map::Range> { let start = ptr.offset.saturating_sub(self.pointer_size() - 1); let end = ptr.offset + size; Ok(self.get(ptr.alloc_id)?.relocations.range(Included(&start), Excluded(&end))) } - fn clear_relocations(&mut self, ptr: Pointer, size: usize) -> EvalResult<'tcx, ()> { + fn clear_relocations(&mut self, ptr: Pointer, size: u64) -> EvalResult<'tcx, ()> { // Find all relocations overlapping the given range. let keys: Vec<_> = self.relocations(ptr, size)?.map(|(&k, _)| k).collect(); if keys.is_empty() { return Ok(()); } @@ -685,16 +707,16 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - fn check_relocation_edges(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, ()> { + fn check_relocation_edges(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, ()> { let overlapping_start = self.relocations(ptr, 0)?.count(); - let overlapping_end = self.relocations(ptr.offset(size as isize), 0)?.count(); + let overlapping_end = self.relocations(ptr.offset(size), 0)?.count(); if overlapping_start + overlapping_end != 0 { return Err(EvalError::ReadPointerAsBytes); } Ok(()) } - fn copy_relocations(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<'tcx, ()> { + fn copy_relocations(&mut self, src: Pointer, dest: Pointer, size: u64) -> EvalResult<'tcx, ()> { let relocations: Vec<_> = self.relocations(src, size)? .map(|(&offset, &alloc_id)| { // Update relocation offsets for the new positions in the destination allocation. @@ -709,20 +731,21 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { /// Undefined bytes impl<'a, 'tcx> Memory<'a, 'tcx> { // FIXME(solson): This is a very naive, slow version. - fn copy_undef_mask(&mut self, src: Pointer, dest: Pointer, size: usize) -> EvalResult<'tcx, ()> { + fn copy_undef_mask(&mut self, src: Pointer, dest: Pointer, size: u64) -> EvalResult<'tcx, ()> { // The bits have to be saved locally before writing to dest in case src and dest overlap. - let mut v = Vec::with_capacity(size); + 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); v.push(defined); } for (i, defined) in v.into_iter().enumerate() { - self.get_mut(dest.alloc_id)?.undef_mask.set(dest.offset + i, defined); + self.get_mut(dest.alloc_id)?.undef_mask.set(dest.offset + i as u64, defined); } Ok(()) } - fn check_defined(&self, ptr: Pointer, size: usize) -> EvalResult<'tcx, ()> { + fn check_defined(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, ()> { let alloc = self.get(ptr.alloc_id)?; if !alloc.undef_mask.is_range_defined(ptr.offset, ptr.offset + size) { return Err(EvalError::ReadUndefBytes); @@ -730,7 +753,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { Ok(()) } - pub fn mark_definedness(&mut self, ptr: Pointer, size: usize, new_state: bool) + pub fn mark_definedness(&mut self, ptr: Pointer, size: u64, new_state: bool) -> EvalResult<'tcx, ()> { if size == 0 { @@ -809,16 +832,16 @@ fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result, - len: usize, + len: u64, } impl UndefMask { - fn new(size: usize) -> Self { + fn new(size: u64) -> Self { let mut m = UndefMask { blocks: vec![], len: 0, @@ -828,7 +851,7 @@ impl UndefMask { } /// Check whether the range `start..end` (end-exclusive) is entirely defined. - pub fn is_range_defined(&self, start: usize, end: usize) -> bool { + pub fn is_range_defined(&self, start: u64, end: u64) -> bool { if end > self.len { return false; } for i in start..end { if !self.get(i) { return false; } @@ -836,22 +859,22 @@ impl UndefMask { true } - fn set_range(&mut self, start: usize, end: usize, new_state: bool) { + fn set_range(&mut self, start: u64, end: u64, new_state: bool) { let len = self.len; if end > len { self.grow(end - len, new_state); } self.set_range_inbounds(start, end, new_state); } - fn set_range_inbounds(&mut self, start: usize, end: usize, new_state: bool) { + fn set_range_inbounds(&mut self, start: u64, end: u64, new_state: bool) { for i in start..end { self.set(i, new_state); } } - fn get(&self, i: usize) -> bool { + fn get(&self, i: u64) -> bool { let (block, bit) = bit_index(i); (self.blocks[block] & 1 << bit) != 0 } - fn set(&mut self, i: usize, new_state: bool) { + fn set(&mut self, i: u64, new_state: bool) { let (block, bit) = bit_index(i); if new_state { self.blocks[block] |= 1 << bit; @@ -860,24 +883,31 @@ impl UndefMask { } } - fn grow(&mut self, amount: usize, new_state: bool) { - let unused_trailing_bits = self.blocks.len() * BLOCK_SIZE - self.len; + 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; - self.blocks.extend(iter::repeat(0).take(additional_blocks)); + assert_eq!(additional_blocks as usize as u64, additional_blocks); + self.blocks.extend(iter::repeat(0).take(additional_blocks as usize)); } let start = self.len; self.len += amount; self.set_range_inbounds(start, start + amount, new_state); } - fn truncate(&mut self, length: usize) { + fn truncate(&mut self, length: u64) { self.len = length; - self.blocks.truncate(self.len / BLOCK_SIZE + 1); + let truncate = self.len / BLOCK_SIZE + 1; + assert_eq!(truncate as usize as u64, truncate); + self.blocks.truncate(truncate as usize); self.blocks.shrink_to_fit(); } } -fn bit_index(bits: usize) -> (usize, usize) { - (bits / BLOCK_SIZE, bits % BLOCK_SIZE) +fn bit_index(bits: u64) -> (usize, usize) { + let a = bits / BLOCK_SIZE; + let b = bits % BLOCK_SIZE; + assert_eq!(a as usize as u64, a); + assert_eq!(b as usize as u64, b); + (a as usize, b as usize) } diff --git a/src/primval.rs b/src/primval.rs index 15cc88ca4cf..20b08b5a0a1 100644 --- a/src/primval.rs +++ b/src/primval.rs @@ -65,7 +65,7 @@ impl PrimValKind { } } - pub fn from_uint_size(size: usize) -> Self { + pub fn from_uint_size(size: u64) -> Self { match size { 1 => PrimValKind::U8, 2 => PrimValKind::U16, @@ -75,7 +75,7 @@ impl PrimValKind { } } - pub fn from_int_size(size: usize) -> Self { + pub fn from_int_size(size: u64) -> Self { match size { 1 => PrimValKind::I8, 2 => PrimValKind::I16, @@ -119,11 +119,11 @@ impl PrimVal { PrimVal::new(f64_to_bits(f), PrimValKind::F64) } - pub fn from_uint_with_size(n: u64, size: usize) -> Self { + pub fn from_uint_with_size(n: u64, size: u64) -> Self { PrimVal::new(n, PrimValKind::from_uint_size(size)) } - pub fn from_int_with_size(n: i64, size: usize) -> Self { + pub fn from_int_with_size(n: i64, size: u64) -> Self { PrimVal::new(n as u64, PrimValKind::from_int_size(size)) } @@ -139,8 +139,8 @@ impl PrimVal { pub fn to_ptr(self) -> Pointer { self.relocation.map(|alloc_id| { - Pointer::new(alloc_id, self.bits as usize) - }).unwrap_or_else(|| Pointer::from_int(self.bits as usize)) + Pointer::new(alloc_id, self.bits) + }).unwrap_or_else(|| Pointer::from_int(self.bits)) } pub fn try_as_uint<'tcx>(self) -> EvalResult<'tcx, u64> {