]> git.lizzy.rs Git - rust.git/commitdiff
Store layouts of i32 and u32 inside Evaluator
authorDavid Cook <divergentdave@gmail.com>
Sun, 29 Mar 2020 06:38:34 +0000 (01:38 -0500)
committerDavid Cook <divergentdave@gmail.com>
Sun, 5 Apr 2020 15:37:57 +0000 (10:37 -0500)
src/lib.rs
src/machine.rs
src/shims/sync.rs

index 2f381b4a34546f7868ed5dd82cff3175820814a3..82ac2e8d21883ae9b7fd575aa4e511688b2b7a0c 100644 (file)
@@ -51,8 +51,9 @@
 pub use crate::eval::{create_ecx, eval_main, MiriConfig};
 pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
 pub use crate::machine::{
-    AllocExtra, Evaluator, FrameData, MemoryExtra, MiriEvalContext, MiriEvalContextExt,
-    MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
+    AllocExtra, EvalContextExt as MachineEvalContextExt, Evaluator, FrameData, MemoryExtra,
+    MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR,
+    STACK_SIZE,
 };
 pub use crate::mono_hash_map::MonoHashMap;
 pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
index f794453228b84d1fea3d68e971ca661226ce083c..a60ae8a4be21ced6f3a3b9127a4e7bfb83e02461 100644 (file)
@@ -11,7 +11,7 @@
 use rand::rngs::StdRng;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_middle::{mir, ty};
+use rustc_middle::{mir, ty::{self, layout::TyAndLayout}};
 use rustc_target::abi::{LayoutOf, Size};
 use rustc_ast::attr;
 use rustc_span::symbol::{sym, Symbol};
@@ -146,6 +146,39 @@ pub fn init_extern_statics<'tcx, 'mir>(
     }
 }
 
+/// Cached layouts of primitive types
+#[derive(Default)]
+struct PrimitiveLayouts<'tcx> {
+    i32: RefCell<Option<TyAndLayout<'tcx>>>,
+    u32: RefCell<Option<TyAndLayout<'tcx>>>,
+}
+
+impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
+    fn i32(&self, ecx: &MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+        {
+            let layout_ref = self.i32.borrow();
+            if layout_ref.is_some() {
+                return Ok(layout_ref.unwrap());
+            }
+        }
+        let layout = ecx.layout_of(ecx.tcx.types.i32)?;
+        *self.i32.borrow_mut() = Some(layout);
+        Ok(layout)
+    }
+
+    fn u32(&self, ecx: &MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+        {
+            let layout_ref = self.u32.borrow();
+            if layout_ref.is_some() {
+                return Ok(layout_ref.unwrap());
+            }
+        }
+        let layout = ecx.layout_of(ecx.tcx.types.u32)?;
+        *self.u32.borrow_mut() = Some(layout);
+        Ok(layout)
+    }
+}
+
 /// The machine itself.
 pub struct Evaluator<'tcx> {
     /// Environment variables set by `setenv`.
@@ -182,6 +215,9 @@ pub struct Evaluator<'tcx> {
 
     /// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
     pub(crate) time_anchor: Instant,
+
+    /// Cached `TyLayout`s for primitive data types that are commonly used inside Miri.
+    primitive_layouts: PrimitiveLayouts<'tcx>,
 }
 
 impl<'tcx> Evaluator<'tcx> {
@@ -201,6 +237,7 @@ pub(crate) fn new(communicate: bool, validate: bool) -> Self {
             dir_handler: Default::default(),
             panic_payload: None,
             time_anchor: Instant::now(),
+            primitive_layouts: PrimitiveLayouts::default(),
         }
     }
 }
@@ -224,6 +261,20 @@ fn eval_context_mut(&mut self) -> &mut MiriEvalContext<'mir, 'tcx> {
     }
 }
 
+impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {}
+/// Provides convenience methods for use elsewhere
+pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
+    fn i32_layout(&self) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+        let this = self.eval_context_ref();
+        this.machine.primitive_layouts.i32(this)
+    }
+
+    fn u32_layout(&self) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+        let this = self.eval_context_ref();
+        this.machine.primitive_layouts.u32(this)
+    }
+}
+
 /// Machine hook implementations.
 impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
     type MemoryKind = MiriMemoryKind;
index 4e4f8c112e533b71d3dca50e7f2d168ab2a02b05..eac2053493a8cb0b737b6d75bdfd766f17d17102 100644 (file)
@@ -30,8 +30,7 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
     // Ensure that the following read at an offset to the attr pointer is within bounds
     assert_ptr_target_min_size(ecx, attr_op, 4)?;
     let attr_place = ecx.deref_operand(attr_op)?;
-    let i32_layout = ecx.layout_of(ecx.tcx.types.i32)?;
-    let kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, i32_layout, ecx)?;
+    let kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.i32_layout()?, ecx)?;
     ecx.read_scalar(kind_place.into())
 }
 
@@ -43,8 +42,7 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
     // Ensure that the following write at an offset to the attr pointer is within bounds
     assert_ptr_target_min_size(ecx, attr_op, 4)?;
     let attr_place = ecx.deref_operand(attr_op)?;
-    let i32_layout = ecx.layout_of(ecx.tcx.types.i32)?;
-    let kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, i32_layout, ecx)?;
+    let kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.i32_layout()?, ecx)?;
     ecx.write_scalar(kind.into(), kind_place.into())
 }
 
@@ -64,9 +62,8 @@ fn mutex_get_locked_count<'mir, 'tcx: 'mir>(
     // Ensure that the following read at an offset to the mutex pointer is within bounds
     assert_ptr_target_min_size(ecx, mutex_op, 20)?;
     let mutex_place = ecx.deref_operand(mutex_op)?;
-    let u32_layout = ecx.layout_of(ecx.tcx.types.u32)?;
     let locked_count_place =
-        mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, ecx)?;
+        mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
     ecx.read_scalar(locked_count_place.into())
 }
 
@@ -78,9 +75,8 @@ fn mutex_set_locked_count<'mir, 'tcx: 'mir>(
     // Ensure that the following write at an offset to the mutex pointer is within bounds
     assert_ptr_target_min_size(ecx, mutex_op, 20)?;
     let mutex_place = ecx.deref_operand(mutex_op)?;
-    let u32_layout = ecx.layout_of(ecx.tcx.types.u32)?;
     let locked_count_place =
-        mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, ecx)?;
+        mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
     ecx.write_scalar(locked_count.into(), locked_count_place.into())
 }
 
@@ -91,10 +87,13 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>(
     // Ensure that the following read at an offset to the mutex pointer is within bounds
     assert_ptr_target_min_size(ecx, mutex_op, 20)?;
     let mutex_place = ecx.deref_operand(mutex_op)?;
-    let i32_layout = ecx.layout_of(ecx.tcx.types.i32)?;
     let kind_offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
-    let kind_place =
-        mutex_place.offset(Size::from_bytes(kind_offset), MemPlaceMeta::None, i32_layout, ecx)?;
+    let kind_place = mutex_place.offset(
+        Size::from_bytes(kind_offset),
+        MemPlaceMeta::None,
+        ecx.i32_layout()?,
+        ecx,
+    )?;
     ecx.read_scalar(kind_place.into())
 }
 
@@ -106,10 +105,13 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
     // Ensure that the following write at an offset to the mutex pointer is within bounds
     assert_ptr_target_min_size(ecx, mutex_op, 20)?;
     let mutex_place = ecx.deref_operand(mutex_op)?;
-    let i32_layout = ecx.layout_of(ecx.tcx.types.i32)?;
     let kind_offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
-    let kind_place =
-        mutex_place.offset(Size::from_bytes(kind_offset), MemPlaceMeta::None, i32_layout, ecx)?;
+    let kind_place = mutex_place.offset(
+        Size::from_bytes(kind_offset),
+        MemPlaceMeta::None,
+        ecx.i32_layout()?,
+        ecx,
+    )?;
     ecx.write_scalar(kind.into(), kind_place.into())
 }
 
@@ -128,9 +130,8 @@ fn rwlock_get_readers<'mir, 'tcx: 'mir>(
     // Ensure that the following read at an offset to the rwlock pointer is within bounds
     assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
     let rwlock_place = ecx.deref_operand(rwlock_op)?;
-    let u32_layout = ecx.layout_of(ecx.tcx.types.u32)?;
     let readers_place =
-        rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, ecx)?;
+        rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
     ecx.read_scalar(readers_place.into())
 }
 
@@ -142,9 +143,8 @@ fn rwlock_set_readers<'mir, 'tcx: 'mir>(
     // Ensure that the following write at an offset to the rwlock pointer is within bounds
     assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
     let rwlock_place = ecx.deref_operand(rwlock_op)?;
-    let u32_layout = ecx.layout_of(ecx.tcx.types.u32)?;
     let readers_place =
-        rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, ecx)?;
+        rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
     ecx.write_scalar(readers.into(), readers_place.into())
 }
 
@@ -155,9 +155,8 @@ fn rwlock_get_writers<'mir, 'tcx: 'mir>(
     // Ensure that the following read at an offset to the rwlock pointer is within bounds
     assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
     let rwlock_place = ecx.deref_operand(rwlock_op)?;
-    let u32_layout = ecx.layout_of(ecx.tcx.types.u32)?;
     let writers_place =
-        rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, ecx)?;
+        rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
     ecx.read_scalar(writers_place.into())
 }
 
@@ -169,9 +168,8 @@ fn rwlock_set_writers<'mir, 'tcx: 'mir>(
     // Ensure that the following write at an offset to the rwlock pointer is within bounds
     assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
     let rwlock_place = ecx.deref_operand(rwlock_op)?;
-    let u32_layout = ecx.layout_of(ecx.tcx.types.u32)?;
     let writers_place =
-        rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, ecx)?;
+        rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
     ecx.write_scalar(writers.into(), writers_place.into())
 }