diff --git a/src/interpreter.rs b/src/interpreter.rs index d0faf7dc1533..58a27a46f879 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -530,6 +530,17 @@ fn call_c_abi(&mut self, def_id: DefId, args: &[mir::Operand<'tcx>], dest: Point try!(self.memory.write_ptr(dest, ptr)); } + "__rust_reallocate" => { + let ptr_arg = try!(self.eval_operand(&args[0])); + let _old_size_arg = try!(self.eval_operand(&args[1])); + let size_arg = try!(self.eval_operand(&args[2])); + let _align_arg = try!(self.eval_operand(&args[3])); + let ptr = try!(self.memory.read_ptr(ptr_arg)); + let size = try!(self.memory.read_usize(size_arg)); + try!(self.memory.reallocate(ptr, size as usize)); + try!(self.memory.write_ptr(dest, ptr)); + } + _ => panic!("can't call C ABI function: {}", link_name), } diff --git a/src/memory.rs b/src/memory.rs index 84cd95409b8b..c4f12804c834 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -63,7 +63,7 @@ pub fn size(&self) -> usize { #[derive(Debug)] pub struct Allocation { - pub bytes: Box<[u8]>, + pub bytes: Vec, pub relocations: BTreeMap, pub undef_mask: UndefMask, } @@ -104,7 +104,7 @@ pub fn new() -> Self { pub fn allocate(&mut self, size: usize) -> Pointer { let id = AllocId(self.next_id); let alloc = Allocation { - bytes: vec![0; size].into_boxed_slice(), + bytes: vec![0; size], relocations: BTreeMap::new(), undef_mask: UndefMask::new(size), }; @@ -116,6 +116,30 @@ pub fn allocate(&mut self, size: usize) -> Pointer { } } + // TODO(tsion): 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) -> EvalResult<()> { + if ptr.offset != 0 { + // TODO(tsion): Report error about non-__rust_allocate'd pointer. + panic!() + } + + let alloc = try!(self.get_mut(ptr.alloc_id)); + let size = alloc.bytes.len(); + if new_size > size { + let amount = new_size - size; + alloc.bytes.extend(iter::repeat(0).take(amount)); + alloc.undef_mask.grow(amount, false); + } else if size > new_size { + unimplemented!() + // alloc.bytes.truncate(new_size); + // alloc.undef_mask.len = new_size; + // TODO: potentially remove relocations + } + + Ok(()) + } + //////////////////////////////////////////////////////////////////////////////// // Allocation accessors //////////////////////////////////////////////////////////////////////////////// diff --git a/test/vecs.rs b/test/vecs.rs index e9f6c12b4409..063d7116744d 100755 --- a/test/vecs.rs +++ b/test/vecs.rs @@ -2,7 +2,7 @@ #![allow(dead_code, unused_attributes)] #[miri_run] -fn make_vec() -> Vec { +fn make_vec() -> Vec { let mut v = Vec::with_capacity(4); v.push(1); v.push(2); @@ -10,7 +10,7 @@ fn make_vec() -> Vec { } #[miri_run] -fn make_vec_macro() -> Vec { +fn make_vec_macro() -> Vec { vec![1, 2] } @@ -23,3 +23,12 @@ fn make_vec_macro_repeat() -> Vec { fn vec_into_iter() -> i32 { vec![1, 2, 3, 4].into_iter().fold(0, |x, y| x + y) } + +#[miri_run] +fn vec_reallocate() -> Vec { + let mut v = vec![1, 2]; + v.push(3); + v.push(4); + v.push(5); + v +}