Skip to content

Commit bc54c76

Browse files
committed
Eagerly compute i32 and u32 layouts
1 parent 134d6a2 commit bc54c76

File tree

4 files changed

+83
-74
lines changed

4 files changed

+83
-74
lines changed

src/eval.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
//! Main evaluator loop and setting up the initial stack frame.
22
3-
use std::ffi::OsStr;
43
use std::convert::TryFrom;
4+
use std::ffi::OsStr;
55

66
use rand::rngs::StdRng;
77
use rand::SeedableRng;
88

9-
use rustc_target::abi::LayoutOf;
10-
use rustc_middle::ty::{self, TyCtxt};
119
use rustc_hir::def_id::DefId;
10+
use rustc_middle::ty::{self, layout::LayoutCx, TyCtxt};
11+
use rustc_target::abi::LayoutOf;
1212

1313
use crate::*;
1414

@@ -60,10 +60,13 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
6060
main_id: DefId,
6161
config: MiriConfig,
6262
) -> InterpResult<'tcx, (InterpCx<'mir, 'tcx, Evaluator<'tcx>>, MPlaceTy<'tcx, Tag>)> {
63+
let tcx_at = tcx.at(rustc_span::source_map::DUMMY_SP);
64+
let param_env = ty::ParamEnv::reveal_all();
65+
let layout_cx = LayoutCx { tcx, param_env };
6366
let mut ecx = InterpCx::new(
64-
tcx.at(rustc_span::source_map::DUMMY_SP),
65-
ty::ParamEnv::reveal_all(),
66-
Evaluator::new(config.communicate, config.validate),
67+
tcx_at,
68+
param_env,
69+
Evaluator::new(config.communicate, config.validate, layout_cx),
6770
MemoryExtra::new(
6871
StdRng::seed_from_u64(config.seed.unwrap_or(0)),
6972
config.stacked_borrows,

src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,8 @@ pub use crate::diagnostics::{
5151
pub use crate::eval::{create_ecx, eval_main, MiriConfig};
5252
pub use crate::helpers::EvalContextExt as HelpersEvalContextExt;
5353
pub use crate::machine::{
54-
AllocExtra, EvalContextExt as MachineEvalContextExt, Evaluator, FrameData, MemoryExtra,
55-
MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR,
56-
STACK_SIZE,
54+
AllocExtra, Evaluator, FrameData, MemoryExtra, MiriEvalContext, MiriEvalContextExt,
55+
MiriMemoryKind, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
5756
};
5857
pub use crate::mono_hash_map::MonoHashMap;
5958
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;

src/machine.rs

Lines changed: 30 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,18 @@ use std::time::Instant;
1010
use log::trace;
1111
use rand::rngs::StdRng;
1212

13-
use rustc_data_structures::fx::FxHashMap;
14-
use rustc_middle::{mir, ty::{self, layout::TyAndLayout}};
15-
use rustc_target::abi::{LayoutOf, Size};
1613
use rustc_ast::attr;
14+
use rustc_data_structures::fx::FxHashMap;
15+
use rustc_middle::{
16+
mir,
17+
ty::{
18+
self,
19+
layout::{LayoutCx, LayoutError, TyAndLayout},
20+
TyCtxt,
21+
},
22+
};
1723
use rustc_span::symbol::{sym, Symbol};
24+
use rustc_target::abi::{LayoutOf, Size};
1825

1926
use crate::*;
2027

@@ -146,36 +153,18 @@ impl MemoryExtra {
146153
}
147154
}
148155

149-
/// Cached layouts of primitive types
150-
#[derive(Default)]
151-
struct PrimitiveLayouts<'tcx> {
152-
i32: RefCell<Option<TyAndLayout<'tcx>>>,
153-
u32: RefCell<Option<TyAndLayout<'tcx>>>,
156+
/// Precomputed layouts of primitive types
157+
pub(crate) struct PrimitiveLayouts<'tcx> {
158+
pub(crate) i32: TyAndLayout<'tcx>,
159+
pub(crate) u32: TyAndLayout<'tcx>,
154160
}
155161

156162
impl<'mir, 'tcx: 'mir> PrimitiveLayouts<'tcx> {
157-
fn i32(&self, ecx: &MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
158-
{
159-
let layout_ref = self.i32.borrow();
160-
if layout_ref.is_some() {
161-
return Ok(layout_ref.unwrap());
162-
}
163-
}
164-
let layout = ecx.layout_of(ecx.tcx.types.i32)?;
165-
*self.i32.borrow_mut() = Some(layout);
166-
Ok(layout)
167-
}
168-
169-
fn u32(&self, ecx: &MiriEvalContext<'mir, 'tcx>) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
170-
{
171-
let layout_ref = self.u32.borrow();
172-
if layout_ref.is_some() {
173-
return Ok(layout_ref.unwrap());
174-
}
175-
}
176-
let layout = ecx.layout_of(ecx.tcx.types.u32)?;
177-
*self.u32.borrow_mut() = Some(layout);
178-
Ok(layout)
163+
fn new(layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>) -> Result<Self, LayoutError<'tcx>> {
164+
Ok(Self {
165+
i32: layout_cx.layout_of(layout_cx.tcx.types.i32)?,
166+
u32: layout_cx.layout_of(layout_cx.tcx.types.u32)?,
167+
})
179168
}
180169
}
181170

@@ -216,14 +205,20 @@ pub struct Evaluator<'tcx> {
216205
/// The "time anchor" for this machine's monotone clock (for `Instant` simulation).
217206
pub(crate) time_anchor: Instant,
218207

219-
/// Cached `TyLayout`s for primitive data types that are commonly used inside Miri.
208+
/// Precomputed `TyLayout`s for primitive data types that are commonly used inside Miri.
220209
/// FIXME: Search through the rest of the codebase for more layout_of() calls that
221-
/// could be cached here.
222-
primitive_layouts: PrimitiveLayouts<'tcx>,
210+
/// could be stored here.
211+
pub(crate) layouts: PrimitiveLayouts<'tcx>,
223212
}
224213

225214
impl<'tcx> Evaluator<'tcx> {
226-
pub(crate) fn new(communicate: bool, validate: bool) -> Self {
215+
pub(crate) fn new(
216+
communicate: bool,
217+
validate: bool,
218+
layout_cx: LayoutCx<'tcx, TyCtxt<'tcx>>,
219+
) -> Self {
220+
let layouts = PrimitiveLayouts::new(layout_cx)
221+
.expect("Couldn't get layouts of primitive types");
227222
Evaluator {
228223
// `env_vars` could be initialized properly here if `Memory` were available before
229224
// calling this method.
@@ -239,7 +234,7 @@ impl<'tcx> Evaluator<'tcx> {
239234
dir_handler: Default::default(),
240235
panic_payload: None,
241236
time_anchor: Instant::now(),
242-
primitive_layouts: PrimitiveLayouts::default(),
237+
layouts,
243238
}
244239
}
245240
}
@@ -263,20 +258,6 @@ impl<'mir, 'tcx> MiriEvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx>
263258
}
264259
}
265260

266-
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for MiriEvalContext<'mir, 'tcx> {}
267-
/// Provides convenience methods for use elsewhere
268-
pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
269-
fn i32_layout(&self) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
270-
let this = self.eval_context_ref();
271-
this.machine.primitive_layouts.i32(this)
272-
}
273-
274-
fn u32_layout(&self) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
275-
let this = self.eval_context_ref();
276-
this.machine.primitive_layouts.u32(this)
277-
}
278-
}
279-
280261
/// Machine hook implementations.
281262
impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> {
282263
type MemoryKind = MiriMemoryKind;

src/shims/sync.rs

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
3131
// Ensure that the following read at an offset to the attr pointer is within bounds
3232
assert_ptr_target_min_size(ecx, attr_op, 4)?;
3333
let attr_place = ecx.deref_operand(attr_op)?;
34-
let kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.i32_layout()?, ecx)?;
34+
let kind_place =
35+
attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.machine.layouts.i32, ecx)?;
3536
ecx.read_scalar(kind_place.into())
3637
}
3738

@@ -43,7 +44,8 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
4344
// Ensure that the following write at an offset to the attr pointer is within bounds
4445
assert_ptr_target_min_size(ecx, attr_op, 4)?;
4546
let attr_place = ecx.deref_operand(attr_op)?;
46-
let kind_place = attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.i32_layout()?, ecx)?;
47+
let kind_place =
48+
attr_place.offset(Size::ZERO, MemPlaceMeta::None, ecx.machine.layouts.i32, ecx)?;
4749
ecx.write_scalar(kind.into(), kind_place.into())
4850
}
4951

@@ -63,8 +65,12 @@ fn mutex_get_locked_count<'mir, 'tcx: 'mir>(
6365
// Ensure that the following read at an offset to the mutex pointer is within bounds
6466
assert_ptr_target_min_size(ecx, mutex_op, 20)?;
6567
let mutex_place = ecx.deref_operand(mutex_op)?;
66-
let locked_count_place =
67-
mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
68+
let locked_count_place = mutex_place.offset(
69+
Size::from_bytes(4),
70+
MemPlaceMeta::None,
71+
ecx.machine.layouts.u32,
72+
ecx,
73+
)?;
6874
ecx.read_scalar(locked_count_place.into())
6975
}
7076

@@ -76,8 +82,12 @@ fn mutex_set_locked_count<'mir, 'tcx: 'mir>(
7682
// Ensure that the following write at an offset to the mutex pointer is within bounds
7783
assert_ptr_target_min_size(ecx, mutex_op, 20)?;
7884
let mutex_place = ecx.deref_operand(mutex_op)?;
79-
let locked_count_place =
80-
mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
85+
let locked_count_place = mutex_place.offset(
86+
Size::from_bytes(4),
87+
MemPlaceMeta::None,
88+
ecx.machine.layouts.u32,
89+
ecx,
90+
)?;
8191
ecx.write_scalar(locked_count.into(), locked_count_place.into())
8292
}
8393

@@ -92,7 +102,7 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>(
92102
let kind_place = mutex_place.offset(
93103
Size::from_bytes(kind_offset),
94104
MemPlaceMeta::None,
95-
ecx.i32_layout()?,
105+
ecx.machine.layouts.i32,
96106
ecx,
97107
)?;
98108
ecx.read_scalar(kind_place.into())
@@ -110,7 +120,7 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
110120
let kind_place = mutex_place.offset(
111121
Size::from_bytes(kind_offset),
112122
MemPlaceMeta::None,
113-
ecx.i32_layout()?,
123+
ecx.machine.layouts.i32,
114124
ecx,
115125
)?;
116126
ecx.write_scalar(kind.into(), kind_place.into())
@@ -131,8 +141,12 @@ fn rwlock_get_readers<'mir, 'tcx: 'mir>(
131141
// Ensure that the following read at an offset to the rwlock pointer is within bounds
132142
assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
133143
let rwlock_place = ecx.deref_operand(rwlock_op)?;
134-
let readers_place =
135-
rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
144+
let readers_place = rwlock_place.offset(
145+
Size::from_bytes(4),
146+
MemPlaceMeta::None,
147+
ecx.machine.layouts.u32,
148+
ecx,
149+
)?;
136150
ecx.read_scalar(readers_place.into())
137151
}
138152

@@ -144,8 +158,12 @@ fn rwlock_set_readers<'mir, 'tcx: 'mir>(
144158
// Ensure that the following write at an offset to the rwlock pointer is within bounds
145159
assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
146160
let rwlock_place = ecx.deref_operand(rwlock_op)?;
147-
let readers_place =
148-
rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
161+
let readers_place = rwlock_place.offset(
162+
Size::from_bytes(4),
163+
MemPlaceMeta::None,
164+
ecx.machine.layouts.u32,
165+
ecx,
166+
)?;
149167
ecx.write_scalar(readers.into(), readers_place.into())
150168
}
151169

@@ -156,8 +174,12 @@ fn rwlock_get_writers<'mir, 'tcx: 'mir>(
156174
// Ensure that the following read at an offset to the rwlock pointer is within bounds
157175
assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
158176
let rwlock_place = ecx.deref_operand(rwlock_op)?;
159-
let writers_place =
160-
rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
177+
let writers_place = rwlock_place.offset(
178+
Size::from_bytes(8),
179+
MemPlaceMeta::None,
180+
ecx.machine.layouts.u32,
181+
ecx,
182+
)?;
161183
ecx.read_scalar(writers_place.into())
162184
}
163185

@@ -169,8 +191,12 @@ fn rwlock_set_writers<'mir, 'tcx: 'mir>(
169191
// Ensure that the following write at an offset to the rwlock pointer is within bounds
170192
assert_ptr_target_min_size(ecx, rwlock_op, 12)?;
171193
let rwlock_place = ecx.deref_operand(rwlock_op)?;
172-
let writers_place =
173-
rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, ecx.u32_layout()?, ecx)?;
194+
let writers_place = rwlock_place.offset(
195+
Size::from_bytes(8),
196+
MemPlaceMeta::None,
197+
ecx.machine.layouts.u32,
198+
ecx,
199+
)?;
174200
ecx.write_scalar(writers.into(), writers_place.into())
175201
}
176202

0 commit comments

Comments
 (0)