about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-03-26 21:44:03 +0100
committerGitHub <noreply@github.com>2020-03-26 21:44:03 +0100
commitde3d1e9fa9743db0e99ea41b9c0b127b19d1bbbb (patch)
tree73cc7e0620d17fd8c2cf255b1fe7ed30c0745272 /src
parentb15423e72e48125a40a3192c2d49a48e54b5c314 (diff)
parent4538f8953b3395dd0eac5acae2f2782d89370aff (diff)
downloadrust-de3d1e9fa9743db0e99ea41b9c0b127b19d1bbbb.tar.gz
rust-de3d1e9fa9743db0e99ea41b9c0b127b19d1bbbb.zip
Rollup merge of #70397 - JOE1994:write_wide_str, r=RalfJung
add 'fn write_u16s' to Memory

Added new function `Memory::write_u16s`. Needed in `MIRI` for implementing helper function to write wide_str to memory (for Windows).
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/interpret/memory.rs44
-rw-r--r--src/librustc_mir/lib.rs1
2 files changed, 43 insertions, 2 deletions
diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs
index 8437399752e..7b6de4b0726 100644
--- a/src/librustc_mir/interpret/memory.rs
+++ b/src/librustc_mir/interpret/memory.rs
@@ -833,17 +833,57 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
         ptr: Scalar<M::PointerTag>,
         src: impl IntoIterator<Item = u8>,
     ) -> InterpResult<'tcx> {
-        let src = src.into_iter();
+        let mut src = src.into_iter();
         let size = Size::from_bytes(src.size_hint().0);
         // `write_bytes` checks that this lower bound `size` matches the upper bound and reality.
         let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(1).unwrap())? {
             Some(ptr) => ptr,
-            None => return Ok(()), // zero-sized access
+            None => {
+                // zero-sized access
+                src.next().expect_none("iterator said it was empty but returned an element");
+                return Ok(());
+            }
         };
         let tcx = self.tcx.tcx;
         self.get_raw_mut(ptr.alloc_id)?.write_bytes(&tcx, ptr, src)
     }
 
+    /// Writes the given stream of u16s into memory.
+    ///
+    /// Performs appropriate bounds checks.
+    pub fn write_u16s(
+        &mut self,
+        ptr: Scalar<M::PointerTag>,
+        src: impl IntoIterator<Item = u16>,
+    ) -> InterpResult<'tcx> {
+        let mut src = src.into_iter();
+        let (lower, upper) = src.size_hint();
+        let len = upper.expect("can only write bounded iterators");
+        assert_eq!(lower, len, "can only write iterators with a precise length");
+
+        let size = Size::from_bytes(lower);
+        let ptr = match self.check_ptr_access(ptr, size, Align::from_bytes(2).unwrap())? {
+            Some(ptr) => ptr,
+            None => {
+                // zero-sized access
+                src.next().expect_none("iterator said it was empty but returned an element");
+                return Ok(());
+            }
+        };
+        let tcx = self.tcx.tcx;
+        let allocation = self.get_raw_mut(ptr.alloc_id)?;
+
+        for idx in 0..len {
+            let val = Scalar::from_u16(
+                src.next().expect("iterator was shorter than it said it would be"),
+            );
+            let offset_ptr = ptr.offset(Size::from_bytes(idx) * 2, &tcx)?; // `Size` multiplication
+            allocation.write_scalar(&tcx, offset_ptr, val.into(), Size::from_bytes(2))?;
+        }
+        src.next().expect_none("iterator was longer than it said it would be");
+        Ok(())
+    }
+
     /// Expects the caller to have checked bounds and alignment.
     pub fn copy(
         &mut self,
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 7d3aba3ff03..85e44adc30b 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -24,6 +24,7 @@ Rust MIR: a lowered representation of Rust.
 #![feature(range_is_empty)]
 #![feature(stmt_expr_attributes)]
 #![feature(trait_alias)]
+#![feature(option_expect_none)]
 #![recursion_limit = "256"]
 
 #[macro_use]