]> git.lizzy.rs Git - rust.git/commitdiff
Move some byte and scalar accessors from `Memory` to `Allocation`
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Mon, 12 Nov 2018 08:00:41 +0000 (09:00 +0100)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Sat, 24 Nov 2018 10:36:31 +0000 (11:36 +0100)
src/librustc/mir/interpret/allocation.rs
src/librustc_mir/interpret/memory.rs

index 1856232573c2a449b1cf1209d9de366d1a736ec6..cba51981021a9c9f9161ae0f680678987cf7df02 100644 (file)
@@ -86,6 +86,206 @@ pub fn check_bounds(
     }
 }
 
+/// Reading and writing
+impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
+    pub fn read_c_str(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, &[u8]> {
+        let alloc = self.get(ptr.alloc_id)?;
+        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
+        let offset = ptr.offset.bytes() as usize;
+        match alloc.bytes[offset..].iter().position(|&c| c == 0) {
+            Some(size) => {
+                let p1 = Size::from_bytes((size + 1) as u64);
+                self.check_relocations(ptr, p1)?;
+                self.check_defined(ptr, p1)?;
+                Ok(&alloc.bytes[offset..offset + size])
+            }
+            None => err!(UnterminatedCString(ptr.erase_tag())),
+        }
+    }
+
+    pub fn check_bytes(
+        &self,
+        ptr: Scalar<M::PointerTag>,
+        size: Size,
+        allow_ptr_and_undef: bool,
+    ) -> EvalResult<'tcx> {
+        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
+        let align = Align::from_bytes(1).unwrap();
+        if size.bytes() == 0 {
+            self.check_align(ptr, align)?;
+            return Ok(());
+        }
+        let ptr = ptr.to_ptr()?;
+        // Check bounds, align and relocations on the edges
+        self.get_bytes_with_undef_and_ptr(ptr, size, align)?;
+        // Check undef and ptr
+        if !allow_ptr_and_undef {
+            self.check_defined(ptr, size)?;
+            self.check_relocations(ptr, size)?;
+        }
+        Ok(())
+    }
+
+    pub fn read_bytes(&self, ptr: Scalar<M::PointerTag>, size: Size) -> EvalResult<'tcx, &[u8]> {
+        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
+        let align = Align::from_bytes(1).unwrap();
+        if size.bytes() == 0 {
+            self.check_align(ptr, align)?;
+            return Ok(&[]);
+        }
+        self.get_bytes(ptr.to_ptr()?, size, align)
+    }
+
+    pub fn write_bytes(&mut self, ptr: Scalar<M::PointerTag>, src: &[u8]) -> EvalResult<'tcx> {
+        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
+        let align = Align::from_bytes(1).unwrap();
+        if src.is_empty() {
+            self.check_align(ptr, align)?;
+            return Ok(());
+        }
+        let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?;
+        bytes.clone_from_slice(src);
+        Ok(())
+    }
+
+    pub fn write_repeat(
+        &mut self,
+        ptr: Scalar<M::PointerTag>,
+        val: u8,
+        count: Size
+    ) -> EvalResult<'tcx> {
+        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
+        let align = Align::from_bytes(1).unwrap();
+        if count.bytes() == 0 {
+            self.check_align(ptr, align)?;
+            return Ok(());
+        }
+        let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?;
+        for b in bytes {
+            *b = val;
+        }
+        Ok(())
+    }
+
+    /// Read a *non-ZST* scalar
+    pub fn read_scalar(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align,
+        size: Size
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
+        // get_bytes_unchecked tests alignment and relocation edges
+        let bytes = self.get_bytes_with_undef_and_ptr(
+            ptr, size, ptr_align.min(self.int_align(size))
+        )?;
+        // Undef check happens *after* we established that the alignment is correct.
+        // We must not return Ok() for unaligned pointers!
+        if self.check_defined(ptr, size).is_err() {
+            // this inflates undefined bytes to the entire scalar, even if only a few
+            // bytes are undefined
+            return Ok(ScalarMaybeUndef::Undef);
+        }
+        // Now we do the actual reading
+        let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap();
+        // See if we got a pointer
+        if size != self.pointer_size() {
+            // *Now* better make sure that the inside also is free of relocations.
+            self.check_relocations(ptr, size)?;
+        } else {
+            let alloc = self.get(ptr.alloc_id)?;
+            match alloc.relocations.get(&ptr.offset) {
+                Some(&(tag, alloc_id)) => {
+                    let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag);
+                    return Ok(ScalarMaybeUndef::Scalar(ptr.into()))
+                }
+                None => {},
+            }
+        }
+        // We don't. Just return the bits.
+        Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
+    }
+
+    pub fn read_ptr_sized(
+        &self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align
+    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
+        self.read_scalar(ptr, ptr_align, self.pointer_size())
+    }
+
+    /// Write a *non-ZST* scalar
+    pub fn write_scalar(
+        &mut self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align,
+        val: ScalarMaybeUndef<M::PointerTag>,
+        type_size: Size,
+    ) -> EvalResult<'tcx> {
+        let val = match val {
+            ScalarMaybeUndef::Scalar(scalar) => scalar,
+            ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
+        };
+
+        let bytes = match val {
+            Scalar::Ptr(val) => {
+                assert_eq!(type_size, self.pointer_size());
+                val.offset.bytes() as u128
+            }
+
+            Scalar::Bits { bits, size } => {
+                assert_eq!(size as u64, type_size.bytes());
+                debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
+                    "Unexpected value of size {} when writing to memory", size);
+                bits
+            },
+        };
+
+        {
+            // get_bytes_mut checks alignment
+            let endian = self.tcx.data_layout.endian;
+            let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?;
+            write_target_uint(endian, dst, bytes).unwrap();
+        }
+
+        // See if we have to also write a relocation
+        match val {
+            Scalar::Ptr(val) => {
+                self.get_mut(ptr.alloc_id)?.relocations.insert(
+                    ptr.offset,
+                    (val.tag, val.alloc_id),
+                );
+            }
+            _ => {}
+        }
+
+        Ok(())
+    }
+
+    pub fn write_ptr_sized(
+        &mut self,
+        ptr: Pointer<M::PointerTag>,
+        ptr_align: Align,
+        val: ScalarMaybeUndef<M::PointerTag>
+    ) -> EvalResult<'tcx> {
+        let ptr_size = self.pointer_size();
+        self.write_scalar(ptr.into(), ptr_align, val, ptr_size)
+    }
+
+    fn int_align(&self, size: Size) -> Align {
+        // We assume pointer-sized integers have the same alignment as pointers.
+        // We also assume signed and unsigned integers of the same size have the same alignment.
+        let ity = match size.bytes() {
+            1 => layout::I8,
+            2 => layout::I16,
+            4 => layout::I32,
+            8 => layout::I64,
+            16 => layout::I128,
+            _ => bug!("bad integer size: {}", size.bytes()),
+        };
+        ity.align(self).abi
+    }
+}
+
 /// Byte accessors
 impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
     /// The last argument controls whether we error out when there are undefined
index 9f8e8fc921af887610f9d694624b7deb934d25f2..69789637927d94d0969617ca67f488a8337c93dd 100644 (file)
@@ -714,203 +714,6 @@ pub fn copy_repeatedly(
 
         Ok(())
     }
-
-    pub fn read_c_str(&self, ptr: Pointer<M::PointerTag>) -> EvalResult<'tcx, &[u8]> {
-        let alloc = self.get(ptr.alloc_id)?;
-        assert_eq!(ptr.offset.bytes() as usize as u64, ptr.offset.bytes());
-        let offset = ptr.offset.bytes() as usize;
-        match alloc.bytes[offset..].iter().position(|&c| c == 0) {
-            Some(size) => {
-                let p1 = Size::from_bytes((size + 1) as u64);
-                self.check_relocations(ptr, p1)?;
-                self.check_defined(ptr, p1)?;
-                Ok(&alloc.bytes[offset..offset + size])
-            }
-            None => err!(UnterminatedCString(ptr.erase_tag())),
-        }
-    }
-
-    pub fn check_bytes(
-        &self,
-        ptr: Scalar<M::PointerTag>,
-        size: Size,
-        allow_ptr_and_undef: bool,
-    ) -> EvalResult<'tcx> {
-        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
-        let align = Align::from_bytes(1).unwrap();
-        if size.bytes() == 0 {
-            self.check_align(ptr, align)?;
-            return Ok(());
-        }
-        let ptr = ptr.to_ptr()?;
-        // Check bounds, align and relocations on the edges
-        self.get_bytes_with_undef_and_ptr(ptr, size, align)?;
-        // Check undef and ptr
-        if !allow_ptr_and_undef {
-            self.check_defined(ptr, size)?;
-            self.check_relocations(ptr, size)?;
-        }
-        Ok(())
-    }
-
-    pub fn read_bytes(&self, ptr: Scalar<M::PointerTag>, size: Size) -> EvalResult<'tcx, &[u8]> {
-        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
-        let align = Align::from_bytes(1).unwrap();
-        if size.bytes() == 0 {
-            self.check_align(ptr, align)?;
-            return Ok(&[]);
-        }
-        self.get_bytes(ptr.to_ptr()?, size, align)
-    }
-
-    pub fn write_bytes(&mut self, ptr: Scalar<M::PointerTag>, src: &[u8]) -> EvalResult<'tcx> {
-        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
-        let align = Align::from_bytes(1).unwrap();
-        if src.is_empty() {
-            self.check_align(ptr, align)?;
-            return Ok(());
-        }
-        let bytes = self.get_bytes_mut(ptr.to_ptr()?, Size::from_bytes(src.len() as u64), align)?;
-        bytes.clone_from_slice(src);
-        Ok(())
-    }
-
-    pub fn write_repeat(
-        &mut self,
-        ptr: Scalar<M::PointerTag>,
-        val: u8,
-        count: Size
-    ) -> EvalResult<'tcx> {
-        // Empty accesses don't need to be valid pointers, but they should still be non-NULL
-        let align = Align::from_bytes(1).unwrap();
-        if count.bytes() == 0 {
-            self.check_align(ptr, align)?;
-            return Ok(());
-        }
-        let bytes = self.get_bytes_mut(ptr.to_ptr()?, count, align)?;
-        for b in bytes {
-            *b = val;
-        }
-        Ok(())
-    }
-
-    /// Read a *non-ZST* scalar
-    pub fn read_scalar(
-        &self,
-        ptr: Pointer<M::PointerTag>,
-        ptr_align: Align,
-        size: Size
-    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
-        // get_bytes_unchecked tests alignment and relocation edges
-        let bytes = self.get_bytes_with_undef_and_ptr(
-            ptr, size, ptr_align.min(self.int_align(size))
-        )?;
-        // Undef check happens *after* we established that the alignment is correct.
-        // We must not return Ok() for unaligned pointers!
-        if self.check_defined(ptr, size).is_err() {
-            // this inflates undefined bytes to the entire scalar, even if only a few
-            // bytes are undefined
-            return Ok(ScalarMaybeUndef::Undef);
-        }
-        // Now we do the actual reading
-        let bits = read_target_uint(self.tcx.data_layout.endian, bytes).unwrap();
-        // See if we got a pointer
-        if size != self.pointer_size() {
-            // *Now* better make sure that the inside also is free of relocations.
-            self.check_relocations(ptr, size)?;
-        } else {
-            let alloc = self.get(ptr.alloc_id)?;
-            match alloc.relocations.get(&ptr.offset) {
-                Some(&(tag, alloc_id)) => {
-                    let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits as u64), tag);
-                    return Ok(ScalarMaybeUndef::Scalar(ptr.into()))
-                }
-                None => {},
-            }
-        }
-        // We don't. Just return the bits.
-        Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
-    }
-
-    pub fn read_ptr_sized(
-        &self,
-        ptr: Pointer<M::PointerTag>,
-        ptr_align: Align
-    ) -> EvalResult<'tcx, ScalarMaybeUndef<M::PointerTag>> {
-        self.read_scalar(ptr, ptr_align, self.pointer_size())
-    }
-
-    /// Write a *non-ZST* scalar
-    pub fn write_scalar(
-        &mut self,
-        ptr: Pointer<M::PointerTag>,
-        ptr_align: Align,
-        val: ScalarMaybeUndef<M::PointerTag>,
-        type_size: Size,
-    ) -> EvalResult<'tcx> {
-        let val = match val {
-            ScalarMaybeUndef::Scalar(scalar) => scalar,
-            ScalarMaybeUndef::Undef => return self.mark_definedness(ptr, type_size, false),
-        };
-
-        let bytes = match val {
-            Scalar::Ptr(val) => {
-                assert_eq!(type_size, self.pointer_size());
-                val.offset.bytes() as u128
-            }
-
-            Scalar::Bits { bits, size } => {
-                assert_eq!(size as u64, type_size.bytes());
-                debug_assert_eq!(truncate(bits, Size::from_bytes(size.into())), bits,
-                    "Unexpected value of size {} when writing to memory", size);
-                bits
-            },
-        };
-
-        {
-            // get_bytes_mut checks alignment
-            let endian = self.tcx.data_layout.endian;
-            let dst = self.get_bytes_mut(ptr, type_size, ptr_align)?;
-            write_target_uint(endian, dst, bytes).unwrap();
-        }
-
-        // See if we have to also write a relocation
-        match val {
-            Scalar::Ptr(val) => {
-                self.get_mut(ptr.alloc_id)?.relocations.insert(
-                    ptr.offset,
-                    (val.tag, val.alloc_id),
-                );
-            }
-            _ => {}
-        }
-
-        Ok(())
-    }
-
-    pub fn write_ptr_sized(
-        &mut self,
-        ptr: Pointer<M::PointerTag>,
-        ptr_align: Align,
-        val: ScalarMaybeUndef<M::PointerTag>
-    ) -> EvalResult<'tcx> {
-        let ptr_size = self.pointer_size();
-        self.write_scalar(ptr.into(), ptr_align, val, ptr_size)
-    }
-
-    fn int_align(&self, size: Size) -> Align {
-        // We assume pointer-sized integers have the same alignment as pointers.
-        // We also assume signed and unsigned integers of the same size have the same alignment.
-        let ity = match size.bytes() {
-            1 => layout::I8,
-            2 => layout::I16,
-            4 => layout::I32,
-            8 => layout::I64,
-            16 => layout::I128,
-            _ => bug!("bad integer size: {}", size.bytes()),
-        };
-        ity.align(self).abi
-    }
 }
 
 /// Undefined bytes