From bc54c7628dbcccc8d727abea591e9ac14ea2fed2 Mon Sep 17 00:00:00 2001 From: David Cook Date: Sun, 5 Apr 2020 16:03:44 -0500 Subject: [PATCH] Eagerly compute i32 and u32 layouts --- src/eval.rs | 15 +++++---- src/lib.rs | 5 ++- src/machine.rs | 79 ++++++++++++++++++----------------------------- src/shims/sync.rs | 58 ++++++++++++++++++++++++---------- 4 files changed, 83 insertions(+), 74 deletions(-) diff --git a/src/eval.rs b/src/eval.rs index 46e66bc0a81e..c3510188e3cb 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -1,14 +1,14 @@ //! Main evaluator loop and setting up the initial stack frame. -use std::ffi::OsStr; use std::convert::TryFrom; +use std::ffi::OsStr; use rand::rngs::StdRng; use rand::SeedableRng; -use rustc_target::abi::LayoutOf; -use rustc_middle::ty::{self, TyCtxt}; use rustc_hir::def_id::DefId; +use rustc_middle::ty::{self, layout::LayoutCx, TyCtxt}; +use rustc_target::abi::LayoutOf; use crate::*; @@ -60,10 +60,13 @@ pub fn create_ecx<'mir, 'tcx: 'mir>( main_id: DefId, config: MiriConfig, ) -> InterpResult<'tcx, (InterpCx<'mir, 'tcx, Evaluator<'tcx>>, MPlaceTy<'tcx, Tag>)> { + let tcx_at = tcx.at(rustc_span::source_map::DUMMY_SP); + let param_env = ty::ParamEnv::reveal_all(); + let layout_cx = LayoutCx { tcx, param_env }; let mut ecx = InterpCx::new( - tcx.at(rustc_span::source_map::DUMMY_SP), - ty::ParamEnv::reveal_all(), - Evaluator::new(config.communicate, config.validate), + tcx_at, + param_env, + Evaluator::new(config.communicate, config.validate, layout_cx), MemoryExtra::new( StdRng::seed_from_u64(config.seed.unwrap_or(0)), config.stacked_borrows, diff --git a/src/lib.rs b/src/lib.rs index 82ac2e8d2188..2f381b4a3454 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -51,9 +51,8 @@ pub use crate::diagnostics::{ pub use crate::eval::{create_ecx, eval_main, MiriConfig}; pub use crate::helpers::EvalContextExt as HelpersEvalContextExt; pub use crate::machine::{ - AllocExtra, EvalContextExt as MachineEvalContextExt, Evaluator, FrameData, MemoryExtra, - MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR, - STACK_SIZE, + AllocExtra, 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; diff --git a/src/machine.rs b/src/machine.rs index bfb832085e0b..26ff23511f73 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -10,11 +10,18 @@ use std::time::Instant; use log::trace; use rand::rngs::StdRng; -use rustc_data_structures::fx::FxHashMap; -use rustc_middle::{mir, ty::{self, layout::TyAndLayout}}; -use rustc_target::abi::{LayoutOf, Size}; use rustc_ast::attr; +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::{ + mir, + ty::{ + self, + layout::{LayoutCx, LayoutError, TyAndLayout}, + TyCtxt, + }, +}; use rustc_span::symbol::{sym, Symbol}; +use rustc_target::abi::{LayoutOf, Size}; use crate::*; @@ -146,36 +153,18 @@ impl MemoryExtra { } } -/// Cached layouts of primitive types -#[derive(Default)] -struct PrimitiveLayouts<'tcx> { - i32: RefCell>>, - u32: RefCell>>, +/// Precomputed layouts of primitive types +pub(crate) struct PrimitiveLayouts<'tcx> { + pub(crate) i32: TyAndLayout<'tcx>, + pub(crate) u32: 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) + fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result> { + Ok(Self { + i32: layout_cx.layout_of(layout_cx.tcx.types.i32)?, + u32: layout_cx.layout_of(layout_cx.tcx.types.u32)?, + }) } } @@ -216,14 +205,20 @@ 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. + /// Precomputed `TyLayout`s for primitive data types that are commonly used inside Miri. /// FIXME: Search through the rest of the codebase for more layout_of() calls that - /// could be cached here. - primitive_layouts: PrimitiveLayouts<'tcx>, + /// could be stored here. + pub(crate) layouts: PrimitiveLayouts<'tcx>, } impl<'tcx> Evaluator<'tcx> { - pub(crate) fn new(communicate: bool, validate: bool) -> Self { + pub(crate) fn new( + communicate: bool, + validate: bool, + layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>, + ) -> Self { + let layouts = PrimitiveLayouts::new(layout_cx) + .expect("Couldn't get layouts of primitive types"); Evaluator { // `env_vars` could be initialized properly here if `Memory` were available before // calling this method. @@ -239,7 +234,7 @@ impl<'tcx> Evaluator<'tcx> { dir_handler: Default::default(), panic_payload: None, time_anchor: Instant::now(), - primitive_layouts: PrimitiveLayouts::default(), + layouts, } } } @@ -263,20 +258,6 @@ impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for 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; diff --git a/src/shims/sync.rs b/src/shims/sync.rs index d7ae32daaa2b..b03dcbfd8969 100644 --- a/src/shims/sync.rs +++ b/src/shims/sync.rs @@ -31,7 +31,8 @@ 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 kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.i32_layout()?, ecx)?; + let kind_place = + attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.machine.layouts.i32, ecx)?; ecx.read_scalar(kind_place.into()) } @@ -43,7 +44,8 @@ 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 kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.i32_layout()?, ecx)?; + let kind_place = + attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.machine.layouts.i32, ecx)?; ecx.write_scalar(kind.into(), kind_place.into()) } @@ -63,8 +65,12 @@ 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 locked_count_place = - mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?; + let locked_count_place = mutex_place.offset( + Size::from_bytes(4), + MemPlaceMeta::None, + ecx.machine.layouts.u32, + ecx, + )?; ecx.read_scalar(locked_count_place.into()) } @@ -76,8 +82,12 @@ 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 locked_count_place = - mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?; + let locked_count_place = mutex_place.offset( + Size::from_bytes(4), + MemPlaceMeta::None, + ecx.machine.layouts.u32, + ecx, + )?; ecx.write_scalar(locked_count.into(), locked_count_place.into()) } @@ -92,7 +102,7 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>( let kind_place = mutex_place.offset( Size::from_bytes(kind_offset), MemPlaceMeta::None, - ecx.i32_layout()?, + ecx.machine.layouts.i32, ecx, )?; ecx.read_scalar(kind_place.into()) @@ -110,7 +120,7 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>( let kind_place = mutex_place.offset( Size::from_bytes(kind_offset), MemPlaceMeta::None, - ecx.i32_layout()?, + ecx.machine.layouts.i32, ecx, )?; ecx.write_scalar(kind.into(), kind_place.into()) @@ -131,8 +141,12 @@ 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 readers_place = - rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?; + let readers_place = rwlock_place.offset( + Size::from_bytes(4), + MemPlaceMeta::None, + ecx.machine.layouts.u32, + ecx, + )?; ecx.read_scalar(readers_place.into()) } @@ -144,8 +158,12 @@ 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 readers_place = - rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?; + let readers_place = rwlock_place.offset( + Size::from_bytes(4), + MemPlaceMeta::None, + ecx.machine.layouts.u32, + ecx, + )?; ecx.write_scalar(readers.into(), readers_place.into()) } @@ -156,8 +174,12 @@ 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 writers_place = - rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?; + let writers_place = rwlock_place.offset( + Size::from_bytes(8), + MemPlaceMeta::None, + ecx.machine.layouts.u32, + ecx, + )?; ecx.read_scalar(writers_place.into()) } @@ -169,8 +191,12 @@ 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 writers_place = - rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?; + let writers_place = rwlock_place.offset( + Size::from_bytes(8), + MemPlaceMeta::None, + ecx.machine.layouts.u32, + ecx, + )?; ecx.write_scalar(writers.into(), writers_place.into()) }