Eagerly compute i32 and u32 layouts

This commit is contained in:
David Cook 2020-04-05 16:03:44 -05:00
parent 134d6a2faa
commit bc54c7628d
4 changed files with 83 additions and 74 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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<Option<TyAndLayout<'tcx>>>,
u32: RefCell<Option<TyAndLayout<'tcx>>>,
/// 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<Self, LayoutError<'tcx>> {
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;

View file

@ -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())
}