Skip to content

Commit a82fe9a

Browse files
committed
Enable more zst writes and reads
1 parent ea6f607 commit a82fe9a

File tree

3 files changed

+161
-15
lines changed

3 files changed

+161
-15
lines changed

src/memory.rs

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -603,9 +603,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
603603
}
604604

605605
fn get_bytes(&self, ptr: Pointer, size: u64, align: u64) -> EvalResult<'tcx, &[u8]> {
606-
if size == 0 {
607-
return Ok(&[]);
608-
}
606+
assert_ne!(size, 0);
609607
if self.relocations(ptr, size)?.count() != 0 {
610608
return Err(EvalError::ReadPointerAsBytes);
611609
}
@@ -614,9 +612,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
614612
}
615613

616614
fn get_bytes_mut(&mut self, ptr: Pointer, size: u64, align: u64) -> EvalResult<'tcx, &mut [u8]> {
617-
if size == 0 {
618-
return Ok(&mut []);
619-
}
615+
assert_ne!(size, 0);
620616
self.clear_relocations(ptr, size)?;
621617
self.mark_definedness(PrimVal::Ptr(ptr), size, true)?;
622618
self.get_bytes_unchecked_mut(ptr, size, align)
@@ -716,17 +712,26 @@ impl<'a, 'tcx> Memory<'a, 'tcx> {
716712
}
717713
}
718714

719-
pub fn read_bytes(&self, ptr: Pointer, size: u64) -> EvalResult<'tcx, &[u8]> {
720-
self.get_bytes(ptr, size, 1)
715+
pub fn read_bytes(&self, ptr: PrimVal, size: u64) -> EvalResult<'tcx, &[u8]> {
716+
if size == 0 {
717+
return Ok(&[]);
718+
}
719+
self.get_bytes(ptr.to_ptr()?, size, 1)
721720
}
722721

723722
pub fn write_bytes(&mut self, ptr: Pointer, src: &[u8]) -> EvalResult<'tcx> {
723+
if src.is_empty() {
724+
return Ok(());
725+
}
724726
let bytes = self.get_bytes_mut(ptr, src.len() as u64, 1)?;
725727
bytes.clone_from_slice(src);
726728
Ok(())
727729
}
728730

729731
pub fn write_repeat(&mut self, ptr: Pointer, val: u8, count: u64) -> EvalResult<'tcx> {
732+
if count == 0 {
733+
return Ok(());
734+
}
730735
let bytes = self.get_bytes_mut(ptr, count, 1)?;
731736
for b in bytes { *b = val; }
732737
Ok(())

src/terminator/mod.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -626,8 +626,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
626626
}
627627

628628
"memcmp" => {
629-
let left = args[0].read_ptr(&self.memory)?.to_ptr()?;
630-
let right = args[1].read_ptr(&self.memory)?.to_ptr()?;
629+
let left = args[0].read_ptr(&self.memory)?;
630+
let right = args[1].read_ptr(&self.memory)?;
631631
let n = self.value_to_primval(args[2], usize)?.to_u64()?;
632632

633633
let result = {
@@ -646,24 +646,24 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
646646
}
647647

648648
"memrchr" => {
649-
let ptr = args[0].read_ptr(&self.memory)?.to_ptr()?;
649+
let ptr = args[0].read_ptr(&self.memory)?;
650650
let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
651651
let num = self.value_to_primval(args[2], usize)?.to_u64()?;
652652
if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().rev().position(|&c| c == val) {
653653
let new_ptr = ptr.offset(num - idx as u64 - 1, self.memory.layout)?;
654-
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
654+
self.write_primval(dest, new_ptr, dest_ty)?;
655655
} else {
656656
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
657657
}
658658
}
659659

660660
"memchr" => {
661-
let ptr = args[0].read_ptr(&self.memory)?.to_ptr()?;
661+
let ptr = args[0].read_ptr(&self.memory)?;
662662
let val = self.value_to_primval(args[1], usize)?.to_u64()? as u8;
663663
let num = self.value_to_primval(args[2], usize)?.to_u64()?;
664664
if let Some(idx) = self.memory.read_bytes(ptr, num)?.iter().position(|&c| c == val) {
665665
let new_ptr = ptr.offset(idx as u64, self.memory.layout)?;
666-
self.write_primval(dest, PrimVal::Ptr(new_ptr), dest_ty)?;
666+
self.write_primval(dest, new_ptr, dest_ty)?;
667667
} else {
668668
self.write_primval(dest, PrimVal::Bytes(0), dest_ty)?;
669669
}
@@ -680,7 +680,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
680680

681681
"write" => {
682682
let fd = self.value_to_primval(args[0], usize)?.to_u64()?;
683-
let buf = args[1].read_ptr(&self.memory)?.to_ptr()?;
683+
let buf = args[1].read_ptr(&self.memory)?;
684684
let n = self.value_to_primval(args[2], usize)?.to_u64()?;
685685
trace!("Called write({:?}, {:?}, {:?})", fd, buf, n);
686686
let result = if fd == 1 || fd == 2 { // stdout/stderr

tests/run-pass/loop-break-value.rs

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(never_type)]
12+
#![allow(unreachable_code)]
13+
14+
#[allow(unused)]
15+
fn never_returns() {
16+
loop {
17+
break loop {};
18+
}
19+
}
20+
21+
pub fn main() {
22+
let value = 'outer: loop {
23+
if 1 == 1 {
24+
break 13;
25+
} else {
26+
let _never: ! = loop {
27+
break loop {
28+
break 'outer panic!();
29+
}
30+
};
31+
}
32+
};
33+
assert_eq!(value, 13);
34+
35+
let x = [1, 3u32, 5];
36+
let y = [17];
37+
let z = [];
38+
let coerced: &[_] = loop {
39+
match 2 {
40+
1 => break &x,
41+
2 => break &y,
42+
3 => break &z,
43+
_ => (),
44+
}
45+
};
46+
assert_eq!(coerced, &[17u32]);
47+
48+
let trait_unified = loop {
49+
break if true {
50+
break Default::default()
51+
} else {
52+
break [13, 14]
53+
};
54+
};
55+
assert_eq!(trait_unified, [0, 0]);
56+
57+
let trait_unified_2 = loop {
58+
if false {
59+
break [String::from("Hello")]
60+
} else {
61+
break Default::default()
62+
};
63+
};
64+
assert_eq!(trait_unified_2, [""]);
65+
66+
let trait_unified_3 = loop {
67+
break if false {
68+
break [String::from("Hello")]
69+
} else {
70+
["Yes".into()]
71+
};
72+
};
73+
assert_eq!(trait_unified_3, ["Yes"]);
74+
75+
let regular_break = loop {
76+
if true {
77+
break;
78+
} else {
79+
break break Default::default();
80+
}
81+
};
82+
assert_eq!(regular_break, ());
83+
84+
let regular_break_2 = loop {
85+
if true {
86+
break Default::default();
87+
} else {
88+
break;
89+
}
90+
};
91+
assert_eq!(regular_break_2, ());
92+
93+
let regular_break_3 = loop {
94+
break if true {
95+
Default::default()
96+
} else {
97+
break;
98+
}
99+
};
100+
assert_eq!(regular_break_3, ());
101+
102+
let regular_break_4 = loop {
103+
break ();
104+
break;
105+
};
106+
assert_eq!(regular_break_4, ());
107+
108+
let regular_break_5 = loop {
109+
break;
110+
break ();
111+
};
112+
assert_eq!(regular_break_5, ());
113+
114+
let nested_break_value = 'outer2: loop {
115+
let _a: u32 = 'inner: loop {
116+
if true {
117+
break 'outer2 "hello";
118+
} else {
119+
break 'inner 17;
120+
}
121+
};
122+
panic!();
123+
};
124+
assert_eq!(nested_break_value, "hello");
125+
126+
let break_from_while_cond = loop {
127+
'inner_loop: while break 'inner_loop {
128+
panic!();
129+
}
130+
break 123;
131+
};
132+
assert_eq!(break_from_while_cond, 123);
133+
134+
let break_from_while_to_outer = 'outer_loop: loop {
135+
while break 'outer_loop 567 {
136+
panic!("from_inner");
137+
}
138+
panic!("from outer");
139+
};
140+
assert_eq!(break_from_while_to_outer, 567);
141+
}

0 commit comments

Comments
 (0)