From a82fe9ae0c770d540e9028596035d72b42c8d0e7 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Tue, 20 Jun 2017 16:26:53 +0200 Subject: [PATCH] Enable more zst writes and reads --- src/memory.rs | 21 +++-- src/terminator/mod.rs | 14 +-- tests/run-pass/loop-break-value.rs | 141 +++++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 15 deletions(-) create mode 100644 tests/run-pass/loop-break-value.rs diff --git a/src/memory.rs b/src/memory.rs index 8aab55e0239..ac2d391f421 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -603,9 +603,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } fn get_bytes(&self, ptr: Pointer, size: u64, align: u64) -> EvalResult<'tcx, &[u8]> { - if size == 0 { - return Ok(&[]); - } + assert_ne!(size, 0); if self.relocations(ptr, size)?.count() != 0 { return Err(EvalError::ReadPointerAsBytes); } @@ -614,9 +612,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } fn get_bytes_mut(&mut self, ptr: Pointer, size: u64, align: u64) -> EvalResult<'tcx, &mut [u8]> { - if size == 0 { - return Ok(&mut []); - } + assert_ne!(size, 0); self.clear_relocations(ptr, size)?; self.mark_definedness(PrimVal::Ptr(ptr), size, true)?; self.get_bytes_unchecked_mut(ptr, size, align) @@ -716,17 +712,26 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } } - pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> { - self.get_bytes(ptr, size, 1) + pub fn read_bytes(&self, ptr: PrimVal, size: u64) -> EvalResult<'tcx, &[u8]> { + if size == 0 { + return Ok(&[]); + } + self.get_bytes(ptr.to_ptr()?, size, 1) } 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, src.len() as u64, 1)?; bytes.clone_from_slice(src); Ok(()) } pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> { + if count == 0 { + return Ok(()); + } let bytes = self.get_bytes_mut(ptr, count, 1)?; for b in bytes { *b = val; } Ok(()) diff --git a/src/terminator/mod.rs b/src/terminator/mod.rs index 6ec607295dc..d4e169cbcfb 100644 --- a/src/terminator/mod.rs +++ b/src/terminator/mod.rs @@ -626,8 +626,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "memcmp" => { - let left = args[0].read_ptr(&self.memory)?.to_ptr()?; - let right = args[1].read_ptr(&self.memory)?.to_ptr()?; + 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)?.to_u64()?; let result = { @@ -646,24 +646,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } "memrchr" => { - let ptr = args[0].read_ptr(&self.memory)?.to_ptr()?; + let ptr = args[0].read_ptr(&self.memory)?; let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) { let new_ptr = ptr.offset(num - idx as u64 - 1, self.memory.layout)?; - self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?; + self.write_primval(dest, new_ptr, dest_ty)?; } else { self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?; } } "memchr" => { - let ptr = args[0].read_ptr(&self.memory)?.to_ptr()?; + let ptr = args[0].read_ptr(&self.memory)?; let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8; let num = self.value_to_primval(args[2], usize)?.to_u64()?; if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) { let new_ptr = ptr.offset(idx as u64, self.memory.layout)?; - self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?; + self.write_primval(dest, new_ptr, dest_ty)?; } else { self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?; } @@ -680,7 +680,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "write" => { let fd = self.value_to_primval(args[0], usize)?.to_u64()?; - let buf = args[1].read_ptr(&self.memory)?.to_ptr()?; + let buf = args[1].read_ptr(&self.memory)?; let n = self.value_to_primval(args[2], usize)?.to_u64()?; trace!("Called write({:?}, {:?}, {:?})", fd, buf, n); let result = if fd == 1 || fd == 2 { // stdout/stderr diff --git a/tests/run-pass/loop-break-value.rs b/tests/run-pass/loop-break-value.rs new file mode 100644 index 00000000000..8631909a2a9 --- /dev/null +++ b/tests/run-pass/loop-break-value.rs @@ -0,0 +1,141 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(never_type)] +#![allow(unreachable_code)] + +#[allow(unused)] +fn never_returns() { + loop { + break loop {}; + } +} + +pub fn main() { + let value = 'outer: loop { + if 1 == 1 { + break 13; + } else { + let _never: ! = loop { + break loop { + break 'outer panic!(); + } + }; + } + }; + assert_eq!(value, 13); + + let x = [1, 3u32, 5]; + let y = [17]; + let z = []; + let coerced: &[_] = loop { + match 2 { + 1 => break &x, + 2 => break &y, + 3 => break &z, + _ => (), + } + }; + assert_eq!(coerced, &[17u32]); + + let trait_unified = loop { + break if true { + break Default::default() + } else { + break [13, 14] + }; + }; + assert_eq!(trait_unified, [0, 0]); + + let trait_unified_2 = loop { + if false { + break [String::from("Hello")] + } else { + break Default::default() + }; + }; + assert_eq!(trait_unified_2, [""]); + + let trait_unified_3 = loop { + break if false { + break [String::from("Hello")] + } else { + ["Yes".into()] + }; + }; + assert_eq!(trait_unified_3, ["Yes"]); + + let regular_break = loop { + if true { + break; + } else { + break break Default::default(); + } + }; + assert_eq!(regular_break, ()); + + let regular_break_2 = loop { + if true { + break Default::default(); + } else { + break; + } + }; + assert_eq!(regular_break_2, ()); + + let regular_break_3 = loop { + break if true { + Default::default() + } else { + break; + } + }; + assert_eq!(regular_break_3, ()); + + let regular_break_4 = loop { + break (); + break; + }; + assert_eq!(regular_break_4, ()); + + let regular_break_5 = loop { + break; + break (); + }; + assert_eq!(regular_break_5, ()); + + let nested_break_value = 'outer2: loop { + let _a: u32 = 'inner: loop { + if true { + break 'outer2 "hello"; + } else { + break 'inner 17; + } + }; + panic!(); + }; + assert_eq!(nested_break_value, "hello"); + + let break_from_while_cond = loop { + 'inner_loop: while break 'inner_loop { + panic!(); + } + break 123; + }; + assert_eq!(break_from_while_cond, 123); + + let break_from_while_to_outer = 'outer_loop: loop { + while break 'outer_loop 567 { + panic!("from_inner"); + } + panic!("from outer"); + }; + assert_eq!(break_from_while_to_outer, 567); +}