Eagerly compute i32 and u32 layouts
This commit is contained in:
parent
134d6a2faa
commit
bc54c7628d
4 changed files with 83 additions and 74 deletions
15
src/eval.rs
15
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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue