Enable more zst writes and reads
This commit is contained in:
parent
ea6f6079ca
commit
a82fe9ae0c
@ -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(())
|
||||
|
@ -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
|
||||
|
141
tests/run-pass/loop-break-value.rs
Normal file
141
tests/run-pass/loop-break-value.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user