From 4b831569f67a8e8bd5131f92966cd186784b495f Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 5 Jul 2016 09:08:24 +0200 Subject: [PATCH 1/8] implement floats by running the ops on the host architecture --- src/interpreter/mod.rs | 24 +++++++++++++++++++++--- src/memory.rs | 3 +++ src/primval.rs | 35 +++++++++++++++++++++++++++++++++++ tests/run-pass/floats.rs | 8 ++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/run-pass/floats.rs diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 4e564005f23f..8ca37a651771 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -169,7 +169,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // TODO(solson): Try making const_to_primval instead. fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> { use rustc::middle::const_val::ConstVal::*; - use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; + use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstFloat}; + use std::mem::transmute; macro_rules! i2p { ($i:ident, $n:expr) => {{ let ptr = self.memory.allocate($n); @@ -178,7 +179,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { }} } match *const_val { - Float(_f) => unimplemented!(), + Float(ConstFloat::F32(f)) => { + let i = unsafe { transmute::<_, u32>(f) }; + i2p!(i, 4) + }, + Float(ConstFloat::F64(f)) => { + let i = unsafe { transmute::<_, u64>(f) }; + i2p!(i, 8) + }, + Float(ConstFloat::FInfer{..}) => unreachable!(), Integral(ConstInt::Infer(_)) => unreachable!(), Integral(ConstInt::InferSigned(_)) => unreachable!(), Integral(ConstInt::I8(i)) => i2p!(i, 1), @@ -824,7 +833,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { - use syntax::ast::{IntTy, UintTy}; + use syntax::ast::{IntTy, UintTy, FloatTy}; + use std::mem::transmute; let val = match (self.memory.pointer_size(), &ty.sty) { (_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?), (_, &ty::TyChar) => { @@ -848,6 +858,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { (_, &ty::TyUint(UintTy::U32)) => PrimVal::U32(self.memory.read_uint(ptr, 4)? as u32), (8, &ty::TyUint(UintTy::Us)) | (_, &ty::TyUint(UintTy::U64)) => PrimVal::U64(self.memory.read_uint(ptr, 8)? as u64), + (_, &ty::TyFloat(FloatTy::F32)) => { + let i = self.memory.read_uint(ptr, 4)? as u32; + PrimVal::F32(unsafe { transmute(i) }) + }, + (_, &ty::TyFloat(FloatTy::F64)) => { + let i = self.memory.read_uint(ptr, 8)?; + PrimVal::F64(unsafe { transmute(i) }) + }, (_, &ty::TyFnDef(def_id, substs, fn_ty)) => { PrimVal::FnPtr(self.memory.create_fn_ptr(def_id, substs, fn_ty)) diff --git a/src/memory.rs b/src/memory.rs index f3072b886b81..92f69d575f18 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -394,6 +394,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> { + use std::mem::transmute; let pointer_size = self.pointer_size(); match val { PrimVal::Bool(b) => self.write_bool(ptr, b), @@ -407,6 +408,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8), PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4), PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size), + PrimVal::F32(f) => self.write_uint(ptr, unsafe { transmute::<_, u32>(f) } as u64, 4), + PrimVal::F64(f) => self.write_uint(ptr, unsafe { transmute::<_, u64>(f) }, 8), PrimVal::FnPtr(_p) | PrimVal::AbstractPtr(_p) => unimplemented!(), } diff --git a/src/primval.rs b/src/primval.rs index f3aedfc19743..f6f9a025770a 100644 --- a/src/primval.rs +++ b/src/primval.rs @@ -13,6 +13,8 @@ pub enum PrimVal { FnPtr(Pointer), IntegerPtr(u64), Char(char), + + F32(f32), F64(f64), } /// returns the result of the operation and whether the operation overflowed @@ -57,6 +59,34 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva }) } + macro_rules! float_binops { + ($v:ident, $l:ident, $r:ident) => ({ + match bin_op { + Add => $v($l + $r), + Sub => $v($l - $r), + Mul => $v($l * $r), + Div => $v($l / $r), + Rem => $v($l % $r), + + // invalid float ops + BitXor => unreachable!(), + BitAnd => unreachable!(), + BitOr => unreachable!(), + Shl => unreachable!(), + Shr => unreachable!(), + + // directly comparing floats is questionable + // miri could forbid it, or at least miri as rust const eval should forbid it + Eq => Bool($l == $r), + Ne => Bool($l != $r), + Lt => Bool($l < $r), + Le => Bool($l <= $r), + Gt => Bool($l > $r), + Ge => Bool($l >= $r), + } + }) + } + fn unrelated_ptr_ops<'tcx>(bin_op: mir::BinOp) -> EvalResult<'tcx, PrimVal> { use rustc::mir::repr::BinOp::*; match bin_op { @@ -128,6 +158,8 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva (U16(l), U16(r)) => int_binops!(U16, l, r), (U32(l), U32(r)) => int_binops!(U32, l, r), (U64(l), U64(r)) => int_binops!(U64, l, r), + (F32(l), F32(r)) => float_binops!(F32, l, r), + (F64(l), F64(r)) => float_binops!(F64, l, r), (Char(l), Char(r)) => match bin_op { Eq => Bool(l == r), Ne => Bool(l != r), @@ -211,6 +243,9 @@ pub fn unary_op<'tcx>(un_op: mir::UnOp, val: PrimVal) -> EvalResult<'tcx, PrimVa (Not, U16(n)) => Ok(U16(!n)), (Not, U32(n)) => Ok(U32(!n)), (Not, U64(n)) => Ok(U64(!n)), + + (Neg, F64(n)) => Ok(F64(-n)), + (Neg, F32(n)) => Ok(F32(-n)), _ => Err(EvalError::Unimplemented(format!("unimplemented unary op: {:?}, {:?}", un_op, val))), } } diff --git a/tests/run-pass/floats.rs b/tests/run-pass/floats.rs new file mode 100644 index 000000000000..504fffca7560 --- /dev/null +++ b/tests/run-pass/floats.rs @@ -0,0 +1,8 @@ + +fn main() { + assert_eq!(6.0_f32*6.0_f32, 36.0_f32); + assert_eq!(6.0_f64*6.0_f64, 36.0_f64); + assert_eq!(-{5.0_f32}, -5.0_f32); + assert!((5.0_f32/0.0).is_infinite()); + assert!((-5.0_f32).sqrt().is_nan()); +} From 51ce4a2584f7356702f8e4faa1343e2ce47db5f8 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 6 Jul 2016 11:51:32 +0200 Subject: [PATCH 2/8] use byteorder's write_f{32,64} instead of transmuting --- src/interpreter/mod.rs | 23 +++++++--------- src/memory.rs | 57 +++++++++++++++++++++++++++++++++++++--- tests/run-pass/floats.rs | 3 +++ 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 8ca37a651771..9ef51a041452 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -170,7 +170,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { fn const_to_ptr(&mut self, const_val: &const_val::ConstVal) -> EvalResult<'tcx, Pointer> { use rustc::middle::const_val::ConstVal::*; use rustc_const_math::{ConstInt, ConstIsize, ConstUsize, ConstFloat}; - use std::mem::transmute; macro_rules! i2p { ($i:ident, $n:expr) => {{ let ptr = self.memory.allocate($n); @@ -180,12 +179,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } match *const_val { Float(ConstFloat::F32(f)) => { - let i = unsafe { transmute::<_, u32>(f) }; - i2p!(i, 4) + let ptr = self.memory.allocate(4); + self.memory.write_f32(ptr, f)?; + Ok(ptr) }, Float(ConstFloat::F64(f)) => { - let i = unsafe { transmute::<_, u64>(f) }; - i2p!(i, 8) + let ptr = self.memory.allocate(8); + self.memory.write_f64(ptr, f)?; + Ok(ptr) }, Float(ConstFloat::FInfer{..}) => unreachable!(), Integral(ConstInt::Infer(_)) => unreachable!(), @@ -834,7 +835,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { pub fn read_primval(&mut self, ptr: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx, PrimVal> { use syntax::ast::{IntTy, UintTy, FloatTy}; - use std::mem::transmute; let val = match (self.memory.pointer_size(), &ty.sty) { (_, &ty::TyBool) => PrimVal::Bool(self.memory.read_bool(ptr)?), (_, &ty::TyChar) => { @@ -858,14 +858,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { (_, &ty::TyUint(UintTy::U32)) => PrimVal::U32(self.memory.read_uint(ptr, 4)? as u32), (8, &ty::TyUint(UintTy::Us)) | (_, &ty::TyUint(UintTy::U64)) => PrimVal::U64(self.memory.read_uint(ptr, 8)? as u64), - (_, &ty::TyFloat(FloatTy::F32)) => { - let i = self.memory.read_uint(ptr, 4)? as u32; - PrimVal::F32(unsafe { transmute(i) }) - }, - (_, &ty::TyFloat(FloatTy::F64)) => { - let i = self.memory.read_uint(ptr, 8)?; - PrimVal::F64(unsafe { transmute(i) }) - }, + + (_, &ty::TyFloat(FloatTy::F32)) => PrimVal::F32(self.memory.read_f32(ptr)?), + (_, &ty::TyFloat(FloatTy::F64)) => PrimVal::F64(self.memory.read_f64(ptr)?), (_, &ty::TyFnDef(def_id, substs, fn_ty)) => { PrimVal::FnPtr(self.memory.create_fn_ptr(def_id, substs, fn_ty)) diff --git a/src/memory.rs b/src/memory.rs index 92f69d575f18..293887ba8625 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -394,7 +394,6 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } pub fn write_primval(&mut self, ptr: Pointer, val: PrimVal) -> EvalResult<'tcx, ()> { - use std::mem::transmute; let pointer_size = self.pointer_size(); match val { PrimVal::Bool(b) => self.write_bool(ptr, b), @@ -408,8 +407,8 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { PrimVal::U64(n) => self.write_uint(ptr, n as u64, 8), PrimVal::Char(c) => self.write_uint(ptr, c as u64, 4), PrimVal::IntegerPtr(n) => self.write_uint(ptr, n as u64, pointer_size), - PrimVal::F32(f) => self.write_uint(ptr, unsafe { transmute::<_, u32>(f) } as u64, 4), - PrimVal::F64(f) => self.write_uint(ptr, unsafe { transmute::<_, u64>(f) }, 8), + PrimVal::F32(f) => self.write_f32(ptr, f), + PrimVal::F64(f) => self.write_f64(ptr, f), PrimVal::FnPtr(_p) | PrimVal::AbstractPtr(_p) => unimplemented!(), } @@ -467,6 +466,28 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { let size = self.pointer_size(); self.write_uint(ptr, n, size) } + + pub fn write_f32(&mut self, ptr: Pointer, f: f32) -> EvalResult<'tcx, ()> { + let endianess = self.endianess(); + let b = self.get_bytes_mut(ptr, 4)?; + write_target_f32(endianess, b, f).unwrap(); + Ok(()) + } + + pub fn write_f64(&mut self, ptr: Pointer, f: f64) -> EvalResult<'tcx, ()> { + let endianess = self.endianess(); + let b = self.get_bytes_mut(ptr, 8)?; + write_target_f64(endianess, b, f).unwrap(); + Ok(()) + } + + pub fn read_f32(&self, ptr: Pointer) -> EvalResult<'tcx, f32> { + self.get_bytes(ptr, 4).map(|b| read_target_f32(self.endianess(), b).unwrap()) + } + + pub fn read_f64(&self, ptr: Pointer) -> EvalResult<'tcx, f64> { + self.get_bytes(ptr, 8).map(|b| read_target_f64(self.endianess(), b).unwrap()) + } } /// Relocations @@ -589,6 +610,36 @@ fn read_target_int(endianess: layout::Endian, mut source: &[u8]) -> Result Result<(), byteorder::Error> { + match endianess { + layout::Endian::Little => target.write_f32::(data), + layout::Endian::Big => target.write_f32::(data), + } +} +fn write_target_f64(endianess: layout::Endian, mut target: &mut [u8], data: f64) -> Result<(), byteorder::Error> { + match endianess { + layout::Endian::Little => target.write_f64::(data), + layout::Endian::Big => target.write_f64::(data), + } +} + +fn read_target_f32(endianess: layout::Endian, mut source: &[u8]) -> Result { + match endianess { + layout::Endian::Little => source.read_f32::(), + layout::Endian::Big => source.read_f32::(), + } +} +fn read_target_f64(endianess: layout::Endian, mut source: &[u8]) -> Result { + match endianess { + layout::Endian::Little => source.read_f64::(), + layout::Endian::Big => source.read_f64::(), + } +} + //////////////////////////////////////////////////////////////////////////////// // Undefined byte tracking //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/run-pass/floats.rs b/tests/run-pass/floats.rs index 504fffca7560..9c4d0594d1c9 100644 --- a/tests/run-pass/floats.rs +++ b/tests/run-pass/floats.rs @@ -5,4 +5,7 @@ fn main() { assert_eq!(-{5.0_f32}, -5.0_f32); assert!((5.0_f32/0.0).is_infinite()); assert!((-5.0_f32).sqrt().is_nan()); + let x: u64 = unsafe { std::mem::transmute(42.0_f64) }; + let y: f64 = unsafe { std::mem::transmute(x) }; + assert_eq!(y, 42.0_f64); } From 7613ef0563843f26fb8abdc47dbd2f9e38eb4895 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Wed, 6 Jul 2016 11:53:03 +0200 Subject: [PATCH 3/8] comparing floats is necessary in rare cases --- src/primval.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/primval.rs b/src/primval.rs index f6f9a025770a..966196d8d1a5 100644 --- a/src/primval.rs +++ b/src/primval.rs @@ -75,8 +75,6 @@ pub fn binary_op<'tcx>(bin_op: mir::BinOp, left: PrimVal, right: PrimVal) -> Eva Shl => unreachable!(), Shr => unreachable!(), - // directly comparing floats is questionable - // miri could forbid it, or at least miri as rust const eval should forbid it Eq => Bool($l == $r), Ne => Bool($l != $r), Lt => Bool($l < $r), From 7d2803ae3fa1d5aed6efa56d9d60776fd62d644c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Jul 2016 11:19:55 +0200 Subject: [PATCH 4/8] remove unused extern crate --- src/bin/miri.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index e11ab5a86099..f5b0c6fbf679 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -4,7 +4,6 @@ extern crate getopts; extern crate miri; extern crate rustc; extern crate rustc_driver; -extern crate rustc_plugin; extern crate env_logger; extern crate log_settings; extern crate syntax; From a7d3a85d9e22e978e8156c2ad57b9d3c4a67dd13 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Jul 2016 11:20:09 +0200 Subject: [PATCH 5/8] infer type of the various limits --- src/bin/miri.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/miri.rs b/src/bin/miri.rs index f5b0c6fbf679..14a947302c65 100644 --- a/src/bin/miri.rs +++ b/src/bin/miri.rs @@ -53,9 +53,9 @@ impl<'a> CompilerCalls<'a> for MiriCompilerCalls { match item.node { MetaItemKind::NameValue(ref name, ref value) => { match &**name { - "memory_size" => memory_size = extract_str(value).parse::().expect("not a number"), - "step_limit" => step_limit = extract_str(value).parse::().expect("not a number"), - "stack_limit" => stack_limit = extract_str(value).parse::().expect("not a number"), + "memory_size" => memory_size = extract_str(value).parse().expect("not a number"), + "step_limit" => step_limit = extract_str(value).parse().expect("not a number"), + "stack_limit" => stack_limit = extract_str(value).parse().expect("not a number"), _ => state.session.span_err(item.span, "unknown miri attribute"), } } From 8d3817cfc63674db308e56371ed8f1cc32af4d92 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Jul 2016 11:20:46 +0200 Subject: [PATCH 6/8] use usize instead of u64 for memory limits --- src/error.rs | 6 +++--- src/interpreter/mod.rs | 9 ++++----- src/memory.rs | 18 +++++++++--------- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/error.rs b/src/error.rs index 9952cfd9a7e8..2d723e692352 100644 --- a/src/error.rs +++ b/src/error.rs @@ -30,9 +30,9 @@ pub enum EvalError<'tcx> { Math(Span, ConstMathErr), InvalidChar(u32), OutOfMemory { - allocation_size: u64, - memory_size: u64, - memory_usage: u64, + allocation_size: usize, + memory_size: usize, + memory_usage: usize, }, ExecutionTimeLimitReached, StackFrameLimitReached, diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 34fa9d8de6fd..04d7d9f9d050 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -136,8 +136,7 @@ enum ConstantKind { } impl<'a, 'tcx> EvalContext<'a, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>, memory_size: u64, stack_limit: u64) -> Self { - assert_eq!(stack_limit as usize as u64, stack_limit); + pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>, memory_size: usize, stack_limit: usize) -> Self { EvalContext { tcx: tcx, mir_map: mir_map, @@ -145,7 +144,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { memory: Memory::new(&tcx.data_layout, memory_size), statics: HashMap::new(), stack: Vec::new(), - stack_limit: stack_limit as usize, + stack_limit: stack_limit, } } @@ -937,9 +936,9 @@ pub fn eval_main<'a, 'tcx: 'a>( tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &'a MirMap<'tcx>, node_id: ast::NodeId, - memory_size: u64, + memory_size: usize, step_limit: u64, - stack_limit: u64, + stack_limit: usize, ) { let mir = mir_map.map.get(&node_id).expect("no mir for main function"); let def_id = tcx.map.local_def_id(node_id); diff --git a/src/memory.rs b/src/memory.rs index 2453b1f6e67a..79130b4e24b1 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -67,9 +67,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: u64, + memory_usage: usize, /// Maximum number of virtual bytes that may be allocated - memory_size: u64, + memory_size: usize, /// Function "allocations". They exist solely so pointers have something to point to, and /// we can figure out what they point to. functions: HashMap>, @@ -82,7 +82,7 @@ pub struct Memory<'a, 'tcx> { const ZST_ALLOC_ID: AllocId = AllocId(0); impl<'a, 'tcx> Memory<'a, 'tcx> { - pub fn new(layout: &'a TargetDataLayout, max_memory: u64) -> Self { + pub fn new(layout: &'a TargetDataLayout, max_memory: usize) -> Self { let mut mem = Memory { alloc_map: HashMap::new(), functions: HashMap::new(), @@ -137,14 +137,14 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { if size == 0 { return Ok(Pointer::zst_ptr()); } - if self.memory_size - self.memory_usage < size as u64 { + if self.memory_size - self.memory_usage < size { return Err(EvalError::OutOfMemory { - allocation_size: size as u64, + allocation_size: size, memory_size: self.memory_size, memory_usage: self.memory_usage, }); } - self.memory_usage += size as u64; + self.memory_usage += size; let alloc = Allocation { bytes: vec![0; size], relocations: BTreeMap::new(), @@ -174,14 +174,14 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { if new_size > size { let amount = new_size - size; - self.memory_usage += amount as u64; + self.memory_usage += amount; let alloc = self.get_mut(ptr.alloc_id)?; alloc.bytes.extend(iter::repeat(0).take(amount)); alloc.undef_mask.grow(amount, false); } else if size > new_size { // it's possible to cause miri to use arbitrary amounts of memory that aren't detectable // through the memory_usage value, by allocating a lot and reallocating to zero - self.memory_usage -= (size - new_size) as u64; + self.memory_usage -= size - new_size; self.clear_relocations(ptr.offset(new_size as isize), size - new_size)?; let alloc = self.get_mut(ptr.alloc_id)?; alloc.bytes.truncate(new_size); @@ -202,7 +202,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } if let Some(alloc) = self.alloc_map.remove(&ptr.alloc_id) { - self.memory_usage -= alloc.bytes.len() as u64; + self.memory_usage -= alloc.bytes.len(); } else { debug!("deallocated a pointer twice: {}", ptr.alloc_id); // TODO(solson): Report error about erroneous free. This is blocked on properly tracking From 5381981446320107536a6058e20f2e52283dd8c5 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Jul 2016 11:21:18 +0200 Subject: [PATCH 7/8] shrink_to_fit some vectors to prevent interpreted code from passing the memory limits --- src/memory.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/memory.rs b/src/memory.rs index 79130b4e24b1..f7ee6b61e5ac 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -179,12 +179,11 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { alloc.bytes.extend(iter::repeat(0).take(amount)); alloc.undef_mask.grow(amount, false); } else if size > new_size { - // it's possible to cause miri to use arbitrary amounts of memory that aren't detectable - // through the memory_usage value, by allocating a lot and reallocating to zero self.memory_usage -= size - new_size; self.clear_relocations(ptr.offset(new_size as isize), size - new_size)?; let alloc = self.get_mut(ptr.alloc_id)?; alloc.bytes.truncate(new_size); + alloc.bytes.shrink_to_fit(); alloc.undef_mask.truncate(new_size); } @@ -676,6 +675,7 @@ impl UndefMask { fn truncate(&mut self, length: usize) { self.len = length; self.blocks.truncate(self.len / BLOCK_SIZE + 1); + self.blocks.shrink_to_fit(); } } From 44bef2523552b3764506d027f4afc0d7996e376c Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Thu, 7 Jul 2016 11:30:00 +0200 Subject: [PATCH 8/8] allocating memory for floats can fail, too --- src/interpreter/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 7bef32b1d561..4200340e6a9c 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -183,12 +183,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } match *const_val { Float(ConstFloat::F32(f)) => { - let ptr = self.memory.allocate(4); + let ptr = self.memory.allocate(4)?; self.memory.write_f32(ptr, f)?; Ok(ptr) }, Float(ConstFloat::F64(f)) => { - let ptr = self.memory.allocate(8); + let ptr = self.memory.allocate(8)?; self.memory.write_f64(ptr, f)?; Ok(ptr) },