Skip to content

Commit 3a2252b

Browse files
committed
adjust for earlier init checking in the core engine
1 parent 101c4f2 commit 3a2252b

33 files changed

+163
-200
lines changed

src/concurrency/data_race.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
447447
offset: u64,
448448
layout: TyAndLayout<'tcx>,
449449
atomic: AtomicReadOrd,
450-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
450+
) -> InterpResult<'tcx, Scalar<Provenance>> {
451451
let this = self.eval_context_ref();
452452
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
453453
this.read_scalar_atomic(&value_place, atomic)
@@ -458,7 +458,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
458458
&mut self,
459459
op: &OpTy<'tcx, Provenance>,
460460
offset: u64,
461-
value: impl Into<ScalarMaybeUninit<Provenance>>,
461+
value: impl Into<Scalar<Provenance>>,
462462
layout: TyAndLayout<'tcx>,
463463
atomic: AtomicWriteOrd,
464464
) -> InterpResult<'tcx> {
@@ -472,7 +472,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
472472
&self,
473473
place: &MPlaceTy<'tcx, Provenance>,
474474
atomic: AtomicReadOrd,
475-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
475+
) -> InterpResult<'tcx, Scalar<Provenance>> {
476476
let this = self.eval_context_ref();
477477
this.atomic_access_check(place)?;
478478
// This will read from the last store in the modification order of this location. In case
@@ -490,7 +490,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
490490
/// Perform an atomic write operation at the memory location.
491491
fn write_scalar_atomic(
492492
&mut self,
493-
val: ScalarMaybeUninit<Provenance>,
493+
val: Scalar<Provenance>,
494494
dest: &MPlaceTy<'tcx, Provenance>,
495495
atomic: AtomicWriteOrd,
496496
) -> InterpResult<'tcx> {
@@ -531,10 +531,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
531531
this.validate_atomic_rmw(place, atomic)?;
532532

533533
this.buffered_atomic_rmw(
534-
val.to_scalar_or_uninit(),
534+
val.to_scalar(),
535535
place,
536536
atomic,
537-
old.to_scalar_or_uninit(),
537+
old.to_scalar(),
538538
)?;
539539
Ok(old)
540540
}
@@ -544,9 +544,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
544544
fn atomic_exchange_scalar(
545545
&mut self,
546546
place: &MPlaceTy<'tcx, Provenance>,
547-
new: ScalarMaybeUninit<Provenance>,
547+
new: Scalar<Provenance>,
548548
atomic: AtomicRwOrd,
549-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
549+
) -> InterpResult<'tcx, Scalar<Provenance>> {
550550
let this = self.eval_context_mut();
551551
this.atomic_access_check(place)?;
552552

@@ -574,7 +574,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
574574

575575
this.validate_overlapping_atomic(place)?;
576576
let old = this.allow_data_races_mut(|this| this.read_immediate(&place.into()))?;
577-
let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar()?.to_bool()?;
577+
let lt = this.binary_op(mir::BinOp::Lt, &old, &rhs)?.to_scalar().to_bool()?;
578578

579579
let new_val = if min {
580580
if lt { &old } else { &rhs }
@@ -587,10 +587,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
587587
this.validate_atomic_rmw(place, atomic)?;
588588

589589
this.buffered_atomic_rmw(
590-
new_val.to_scalar_or_uninit(),
590+
new_val.to_scalar(),
591591
place,
592592
atomic,
593-
old.to_scalar_or_uninit(),
593+
old.to_scalar(),
594594
)?;
595595

596596
// Return the old value.
@@ -607,7 +607,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
607607
&mut self,
608608
place: &MPlaceTy<'tcx, Provenance>,
609609
expect_old: &ImmTy<'tcx, Provenance>,
610-
new: ScalarMaybeUninit<Provenance>,
610+
new: Scalar<Provenance>,
611611
success: AtomicRwOrd,
612612
fail: AtomicReadOrd,
613613
can_fail_spuriously: bool,
@@ -627,14 +627,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
627627
// If the operation would succeed, but is "weak", fail some portion
628628
// of the time, based on `success_rate`.
629629
let success_rate = 1.0 - this.machine.cmpxchg_weak_failure_rate;
630-
let cmpxchg_success = eq.to_scalar()?.to_bool()?
630+
let cmpxchg_success = eq.to_scalar().to_bool()?
631631
&& if can_fail_spuriously {
632632
this.machine.rng.get_mut().gen_bool(success_rate)
633633
} else {
634634
true
635635
};
636636
let res = Immediate::ScalarPair(
637-
old.to_scalar_or_uninit(),
637+
old.to_scalar(),
638638
Scalar::from_bool(cmpxchg_success).into(),
639639
);
640640

@@ -644,14 +644,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
644644
if cmpxchg_success {
645645
this.allow_data_races_mut(|this| this.write_scalar(new, &place.into()))?;
646646
this.validate_atomic_rmw(place, success)?;
647-
this.buffered_atomic_rmw(new, place, success, old.to_scalar_or_uninit())?;
647+
this.buffered_atomic_rmw(new, place, success, old.to_scalar())?;
648648
} else {
649649
this.validate_atomic_load(place, fail)?;
650650
// A failed compare exchange is equivalent to a load, reading from the latest store
651651
// in the modification order.
652652
// Since `old` is only a value and not the store element, we need to separately
653653
// find it in our store buffer and perform load_impl on it.
654-
this.perform_read_on_buffered_latest(place, fail, old.to_scalar_or_uninit())?;
654+
this.perform_read_on_buffered_latest(place, fail, old.to_scalar())?;
655655
}
656656

657657
// Return the old value.

src/concurrency/weak_memory.rs

+18-18
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ use std::{
7878
};
7979

8080
use rustc_const_eval::interpret::{
81-
alloc_range, AllocRange, InterpResult, MPlaceTy, ScalarMaybeUninit,
81+
alloc_range, AllocRange, InterpResult, MPlaceTy, Scalar,
8282
};
8383
use rustc_data_structures::fx::FxHashMap;
8484

@@ -130,10 +130,10 @@ struct StoreElement {
130130
/// The timestamp of the storing thread when it performed the store
131131
timestamp: VTimestamp,
132132
/// The value of this store
133-
// FIXME: this means the store is either fully initialized or fully uninitialized;
133+
// FIXME: this means the store must be fully initialized;
134134
// we will have to change this if we want to support atomics on
135-
// partially initialized data.
136-
val: ScalarMaybeUninit<Provenance>,
135+
// (partially) uninitialized data.
136+
val: Scalar<Provenance>,
137137

138138
/// Timestamp of first loads from this store element by each thread
139139
/// Behind a RefCell to keep load op take &self
@@ -180,7 +180,7 @@ impl StoreBufferAlloc {
180180
fn get_or_create_store_buffer<'tcx>(
181181
&self,
182182
range: AllocRange,
183-
init: ScalarMaybeUninit<Provenance>,
183+
init: Scalar<Provenance>,
184184
) -> InterpResult<'tcx, Ref<'_, StoreBuffer>> {
185185
let access_type = self.store_buffers.borrow().access_type(range);
186186
let pos = match access_type {
@@ -205,7 +205,7 @@ impl StoreBufferAlloc {
205205
fn get_or_create_store_buffer_mut<'tcx>(
206206
&mut self,
207207
range: AllocRange,
208-
init: ScalarMaybeUninit<Provenance>,
208+
init: Scalar<Provenance>,
209209
) -> InterpResult<'tcx, &mut StoreBuffer> {
210210
let buffers = self.store_buffers.get_mut();
211211
let access_type = buffers.access_type(range);
@@ -226,7 +226,7 @@ impl StoreBufferAlloc {
226226
}
227227

228228
impl<'mir, 'tcx: 'mir> StoreBuffer {
229-
fn new(init: ScalarMaybeUninit<Provenance>) -> Self {
229+
fn new(init: Scalar<Provenance>) -> Self {
230230
let mut buffer = VecDeque::new();
231231
buffer.reserve(STORE_BUFFER_LIMIT);
232232
let mut ret = Self { buffer };
@@ -259,7 +259,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
259259
is_seqcst: bool,
260260
rng: &mut (impl rand::Rng + ?Sized),
261261
validate: impl FnOnce() -> InterpResult<'tcx>,
262-
) -> InterpResult<'tcx, (ScalarMaybeUninit<Provenance>, LoadRecency)> {
262+
) -> InterpResult<'tcx, (Scalar<Provenance>, LoadRecency)> {
263263
// Having a live borrow to store_buffer while calling validate_atomic_load is fine
264264
// because the race detector doesn't touch store_buffer
265265

@@ -284,7 +284,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
284284

285285
fn buffered_write(
286286
&mut self,
287-
val: ScalarMaybeUninit<Provenance>,
287+
val: Scalar<Provenance>,
288288
global: &DataRaceState,
289289
thread_mgr: &ThreadManager<'_, '_>,
290290
is_seqcst: bool,
@@ -375,7 +375,7 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
375375
/// ATOMIC STORE IMPL in the paper (except we don't need the location's vector clock)
376376
fn store_impl(
377377
&mut self,
378-
val: ScalarMaybeUninit<Provenance>,
378+
val: Scalar<Provenance>,
379379
index: VectorIdx,
380380
thread_clock: &VClock,
381381
is_seqcst: bool,
@@ -421,7 +421,7 @@ impl StoreElement {
421421
&self,
422422
index: VectorIdx,
423423
clocks: &ThreadClockSet,
424-
) -> ScalarMaybeUninit<Provenance> {
424+
) -> Scalar<Provenance> {
425425
let _ = self.loads.borrow_mut().try_insert(index, clocks.clock[index]);
426426
self.val
427427
}
@@ -464,10 +464,10 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
464464

465465
fn buffered_atomic_rmw(
466466
&mut self,
467-
new_val: ScalarMaybeUninit<Provenance>,
467+
new_val: Scalar<Provenance>,
468468
place: &MPlaceTy<'tcx, Provenance>,
469469
atomic: AtomicRwOrd,
470-
init: ScalarMaybeUninit<Provenance>,
470+
init: Scalar<Provenance>,
471471
) -> InterpResult<'tcx> {
472472
let this = self.eval_context_mut();
473473
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
@@ -492,9 +492,9 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
492492
&self,
493493
place: &MPlaceTy<'tcx, Provenance>,
494494
atomic: AtomicReadOrd,
495-
latest_in_mo: ScalarMaybeUninit<Provenance>,
495+
latest_in_mo: Scalar<Provenance>,
496496
validate: impl FnOnce() -> InterpResult<'tcx>,
497-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
497+
) -> InterpResult<'tcx, Scalar<Provenance>> {
498498
let this = self.eval_context_ref();
499499
if let Some(global) = &this.machine.data_race {
500500
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
@@ -529,10 +529,10 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
529529

530530
fn buffered_atomic_write(
531531
&mut self,
532-
val: ScalarMaybeUninit<Provenance>,
532+
val: Scalar<Provenance>,
533533
dest: &MPlaceTy<'tcx, Provenance>,
534534
atomic: AtomicWriteOrd,
535-
init: ScalarMaybeUninit<Provenance>,
535+
init: Scalar<Provenance>,
536536
) -> InterpResult<'tcx> {
537537
let this = self.eval_context_mut();
538538
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr)?;
@@ -576,7 +576,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
576576
&self,
577577
place: &MPlaceTy<'tcx, Provenance>,
578578
atomic: AtomicReadOrd,
579-
init: ScalarMaybeUninit<Provenance>,
579+
init: Scalar<Provenance>,
580580
) -> InterpResult<'tcx> {
581581
let this = self.eval_context_ref();
582582

src/helpers.rs

+16-8
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
116116
let instance = this.resolve_path(path);
117117
let cid = GlobalId { instance, promoted: None };
118118
let const_val = this.eval_to_allocation(cid)?;
119-
let const_val = this.read_scalar(&const_val.into())?;
120-
const_val.check_init()
119+
this.read_scalar(&const_val.into())
121120
}
122121

123122
/// Helper function to get a `libc` constant as a `Scalar`.
@@ -567,7 +566,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
567566
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
568567
let this = self.eval_context_mut();
569568
let errno_place = this.last_error_place()?;
570-
this.read_scalar(&errno_place.into())?.check_init()
569+
this.read_scalar(&errno_place.into())
571570
}
572571

573572
/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
@@ -680,22 +679,31 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
680679
op: &OpTy<'tcx, Provenance>,
681680
offset: u64,
682681
layout: TyAndLayout<'tcx>,
683-
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
682+
) -> InterpResult<'tcx, Scalar<Provenance>> {
684683
let this = self.eval_context_ref();
685684
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
686685
this.read_scalar(&value_place.into())
687686
}
688687

688+
fn write_immediate_at_offset(
689+
&mut self,
690+
op: &OpTy<'tcx, Provenance>,
691+
offset: u64,
692+
value: &ImmTy<'tcx, Provenance>,
693+
) -> InterpResult<'tcx, ()> {
694+
let this = self.eval_context_mut();
695+
let value_place = this.deref_operand_and_offset(op, offset, value.layout)?;
696+
this.write_immediate(**value, &value_place.into())
697+
}
698+
689699
fn write_scalar_at_offset(
690700
&mut self,
691701
op: &OpTy<'tcx, Provenance>,
692702
offset: u64,
693-
value: impl Into<ScalarMaybeUninit<Provenance>>,
703+
value: impl Into<Scalar<Provenance>>,
694704
layout: TyAndLayout<'tcx>,
695705
) -> InterpResult<'tcx, ()> {
696-
let this = self.eval_context_mut();
697-
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
698-
this.write_scalar(value, &value_place.into())
706+
self.write_immediate_at_offset(op, offset, &ImmTy::from_scalar(value.into(), layout))
699707
}
700708

701709
/// Parse a `timespec` struct and return it as a `std::time::Duration`. It returns `None`

src/machine.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ static_assert_size!(Pointer<Provenance>, 24);
149149
// #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
150150
//static_assert_size!(Pointer<Option<Provenance>>, 24);
151151
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
152-
static_assert_size!(ScalarMaybeUninit<Provenance>, 32);
152+
static_assert_size!(Scalar<Provenance>, 32);
153153

154154
impl interpret::Provenance for Provenance {
155155
/// We use absolute addresses in the `offset` of a `Pointer<Provenance>`.
@@ -581,7 +581,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
581581
}
582582

583583
#[inline(always)]
584-
fn force_int_for_alignment_check(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
584+
fn use_addr_for_alignment_check(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
585585
ecx.machine.check_alignment == AlignmentCheck::Int
586586
}
587587

@@ -590,11 +590,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
590590
ecx.machine.validate
591591
}
592592

593-
#[inline(always)]
594-
fn enforce_number_init(_ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
595-
true
596-
}
597-
598593
#[inline(always)]
599594
fn enforce_abi(ecx: &MiriEvalContext<'mir, 'tcx>) -> bool {
600595
ecx.machine.enforce_abi

src/operator.rs

+10-12
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
3232
// Just compare the bits. ScalarPairs are compared lexicographically.
3333
// We thus always compare pairs and simply fill scalars up with 0.
3434
let left = match **left {
35-
Immediate::Scalar(l) => (l.check_init()?.to_bits(size)?, 0),
36-
Immediate::ScalarPair(l1, l2) =>
37-
(l1.check_init()?.to_bits(size)?, l2.check_init()?.to_bits(size)?),
38-
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
35+
Immediate::Scalar(l) => (l.to_bits(size)?, 0),
36+
Immediate::ScalarPair(l1, l2) => (l1.to_bits(size)?, l2.to_bits(size)?),
37+
Immediate::Uninit => panic!("we should never see uninit data here"),
3938
};
4039
let right = match **right {
41-
Immediate::Scalar(r) => (r.check_init()?.to_bits(size)?, 0),
42-
Immediate::ScalarPair(r1, r2) =>
43-
(r1.check_init()?.to_bits(size)?, r2.check_init()?.to_bits(size)?),
44-
Immediate::Uninit => throw_ub!(InvalidUninitBytes(None)),
40+
Immediate::Scalar(r) => (r.to_bits(size)?, 0),
41+
Immediate::ScalarPair(r1, r2) => (r1.to_bits(size)?, r2.to_bits(size)?),
42+
Immediate::Uninit => panic!("we should never see uninit data here"),
4543
};
4644
let res = match bin_op {
4745
Eq => left == right,
@@ -57,8 +55,8 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
5755

5856
Offset => {
5957
assert!(left.layout.ty.is_unsafe_ptr());
60-
let ptr = left.to_scalar()?.to_pointer(self)?;
61-
let offset = right.to_scalar()?.to_machine_isize(self)?;
58+
let ptr = left.to_scalar().to_pointer(self)?;
59+
let offset = right.to_scalar().to_machine_isize(self)?;
6260

6361
let pointee_ty =
6462
left.layout.ty.builtin_deref(true).expect("Offset called on non-ptr type").ty;
@@ -71,11 +69,11 @@ impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
7169
Add | Sub | BitOr | BitAnd | BitXor => {
7270
assert!(left.layout.ty.is_unsafe_ptr());
7371
assert!(right.layout.ty.is_unsafe_ptr());
74-
let ptr = left.to_scalar()?.to_pointer(self)?;
72+
let ptr = left.to_scalar().to_pointer(self)?;
7573
// We do the actual operation with usize-typed scalars.
7674
let left = ImmTy::from_uint(ptr.addr().bytes(), self.machine.layouts.usize);
7775
let right = ImmTy::from_uint(
78-
right.to_scalar()?.to_machine_usize(self)?,
76+
right.to_scalar().to_machine_usize(self)?,
7977
self.machine.layouts.usize,
8078
);
8179
let (result, overflowing, _ty) =

0 commit comments

Comments
 (0)