From: David Cook Date: Sun, 29 Mar 2020 06:38:34 +0000 (-0500) Subject: Store layouts of i32 and u32 inside Evaluator X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=ac8c98da8e806a7e18dcc0cee8201085e5c7abb6;p=rust.git Store layouts of i32 and u32 inside Evaluator --- diff --git a/src/lib.rs b/src/lib.rs index 2f381b4a345..82ac2e8d218 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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; diff --git a/src/machine.rs b/src/machine.rs index f794453228b..a60ae8a4be2 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -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>>, + u32: RefCell>>, +} + +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; diff --git a/src/shims/sync.rs b/src/shims/sync.rs index 4e4f8c112e5..eac2053493a 100644 --- a/src/shims/sync.rs +++ b/src/shims/sync.rs @@ -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()) }