commit
167e5dcad3
@ -1 +1 @@
|
||||
29c5a028b0c92aa5da6a8eb6d6585a389fcf1035
|
||||
a7468c60f8dbf5feb23ad840b174d7e57113a846
|
||||
|
@ -439,11 +439,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriEvalContextExt<'mir, 'tcx> {
|
||||
/// Atomic variant of read_scalar_at_offset.
|
||||
fn read_scalar_at_offset_atomic(
|
||||
&self,
|
||||
op: &OpTy<'tcx, Tag>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
atomic: AtomicReadOrd,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
|
||||
this.read_scalar_atomic(&value_place, atomic)
|
||||
@ -452,9 +452,9 @@ fn read_scalar_at_offset_atomic(
|
||||
/// Atomic variant of write_scalar_at_offset.
|
||||
fn write_scalar_at_offset_atomic(
|
||||
&mut self,
|
||||
op: &OpTy<'tcx, Tag>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
value: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
value: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
atomic: AtomicWriteOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -466,9 +466,9 @@ fn write_scalar_at_offset_atomic(
|
||||
/// Perform an atomic read operation at the memory location.
|
||||
fn read_scalar_atomic(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicReadOrd,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
// This will read from the last store in the modification order of this location. In case
|
||||
// weak memory emulation is enabled, this may not be the store we will pick to actually read from and return.
|
||||
@ -485,8 +485,8 @@ fn read_scalar_atomic(
|
||||
/// Perform an atomic write operation at the memory location.
|
||||
fn write_scalar_atomic(
|
||||
&mut self,
|
||||
val: ScalarMaybeUninit<Tag>,
|
||||
dest: &MPlaceTy<'tcx, Tag>,
|
||||
val: ScalarMaybeUninit<Provenance>,
|
||||
dest: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicWriteOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -504,12 +504,12 @@ fn write_scalar_atomic(
|
||||
/// Perform an atomic operation on a memory location.
|
||||
fn atomic_op_immediate(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
rhs: &ImmTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
rhs: &ImmTy<'tcx, Provenance>,
|
||||
op: mir::BinOp,
|
||||
neg: bool,
|
||||
atomic: AtomicRwOrd,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.validate_overlapping_atomic(place)?;
|
||||
@ -535,10 +535,10 @@ fn atomic_op_immediate(
|
||||
/// scalar value, the old value is returned.
|
||||
fn atomic_exchange_scalar(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
new: ScalarMaybeUninit<Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
new: ScalarMaybeUninit<Provenance>,
|
||||
atomic: AtomicRwOrd,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.validate_overlapping_atomic(place)?;
|
||||
@ -555,11 +555,11 @@ fn atomic_exchange_scalar(
|
||||
/// scalar value, the old value is returned.
|
||||
fn atomic_min_max_scalar(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
rhs: ImmTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
rhs: ImmTy<'tcx, Provenance>,
|
||||
min: bool,
|
||||
atomic: AtomicRwOrd,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.validate_overlapping_atomic(place)?;
|
||||
@ -595,13 +595,13 @@ fn atomic_min_max_scalar(
|
||||
/// identical.
|
||||
fn atomic_compare_exchange_scalar(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
expect_old: &ImmTy<'tcx, Tag>,
|
||||
new: ScalarMaybeUninit<Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
expect_old: &ImmTy<'tcx, Provenance>,
|
||||
new: ScalarMaybeUninit<Provenance>,
|
||||
success: AtomicRwOrd,
|
||||
fail: AtomicReadOrd,
|
||||
can_fail_spuriously: bool,
|
||||
) -> InterpResult<'tcx, Immediate<Tag>> {
|
||||
) -> InterpResult<'tcx, Immediate<Provenance>> {
|
||||
use rand::Rng as _;
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -651,7 +651,7 @@ fn atomic_compare_exchange_scalar(
|
||||
/// associated memory-place and on the current thread.
|
||||
fn validate_atomic_load(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicReadOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
@ -674,7 +674,7 @@ fn validate_atomic_load(
|
||||
/// associated memory-place and on the current thread.
|
||||
fn validate_atomic_store(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicWriteOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -697,7 +697,7 @@ fn validate_atomic_store(
|
||||
/// at the associated memory place and on the current thread.
|
||||
fn validate_atomic_rmw(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicRwOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
use AtomicRwOrd::*;
|
||||
@ -1047,7 +1047,7 @@ fn allow_data_races_mut<R>(
|
||||
/// Generic atomic operation implementation
|
||||
fn validate_atomic_op<A: Debug + Copy>(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: A,
|
||||
description: &str,
|
||||
mut op: impl FnMut(
|
||||
|
@ -83,7 +83,8 @@
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
||||
use crate::{
|
||||
AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, Tag, ThreadManager, VClock, VTimestamp, VectorIdx,
|
||||
AtomicReadOrd, AtomicRwOrd, AtomicWriteOrd, Provenance, ThreadManager, VClock, VTimestamp,
|
||||
VectorIdx,
|
||||
};
|
||||
|
||||
use super::{
|
||||
@ -127,7 +128,7 @@ struct StoreElement {
|
||||
// FIXME: this means the store is either fully initialized or fully uninitialized;
|
||||
// we will have to change this if we want to support atomics on
|
||||
// partially initialized data.
|
||||
val: ScalarMaybeUninit<Tag>,
|
||||
val: ScalarMaybeUninit<Provenance>,
|
||||
|
||||
/// Timestamp of first loads from this store element by each thread
|
||||
/// Behind a RefCell to keep load op take &self
|
||||
@ -174,7 +175,7 @@ pub fn memory_accessed(&self, range: AllocRange, global: &DataRaceState) {
|
||||
fn get_or_create_store_buffer<'tcx>(
|
||||
&self,
|
||||
range: AllocRange,
|
||||
init: ScalarMaybeUninit<Tag>,
|
||||
init: ScalarMaybeUninit<Provenance>,
|
||||
) -> InterpResult<'tcx, Ref<'_, StoreBuffer>> {
|
||||
let access_type = self.store_buffers.borrow().access_type(range);
|
||||
let pos = match access_type {
|
||||
@ -199,7 +200,7 @@ fn get_or_create_store_buffer<'tcx>(
|
||||
fn get_or_create_store_buffer_mut<'tcx>(
|
||||
&mut self,
|
||||
range: AllocRange,
|
||||
init: ScalarMaybeUninit<Tag>,
|
||||
init: ScalarMaybeUninit<Provenance>,
|
||||
) -> InterpResult<'tcx, &mut StoreBuffer> {
|
||||
let buffers = self.store_buffers.get_mut();
|
||||
let access_type = buffers.access_type(range);
|
||||
@ -220,7 +221,7 @@ fn get_or_create_store_buffer_mut<'tcx>(
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx: 'mir> StoreBuffer {
|
||||
fn new(init: ScalarMaybeUninit<Tag>) -> Self {
|
||||
fn new(init: ScalarMaybeUninit<Provenance>) -> Self {
|
||||
let mut buffer = VecDeque::new();
|
||||
buffer.reserve(STORE_BUFFER_LIMIT);
|
||||
let mut ret = Self { buffer };
|
||||
@ -253,7 +254,7 @@ fn buffered_read(
|
||||
is_seqcst: bool,
|
||||
rng: &mut (impl rand::Rng + ?Sized),
|
||||
validate: impl FnOnce() -> InterpResult<'tcx>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
// Having a live borrow to store_buffer while calling validate_atomic_load is fine
|
||||
// because the race detector doesn't touch store_buffer
|
||||
|
||||
@ -278,7 +279,7 @@ fn buffered_read(
|
||||
|
||||
fn buffered_write(
|
||||
&mut self,
|
||||
val: ScalarMaybeUninit<Tag>,
|
||||
val: ScalarMaybeUninit<Provenance>,
|
||||
global: &DataRaceState,
|
||||
thread_mgr: &ThreadManager<'_, '_>,
|
||||
is_seqcst: bool,
|
||||
@ -366,7 +367,7 @@ fn fetch_store<R: rand::Rng + ?Sized>(
|
||||
/// ATOMIC STORE IMPL in the paper (except we don't need the location's vector clock)
|
||||
fn store_impl(
|
||||
&mut self,
|
||||
val: ScalarMaybeUninit<Tag>,
|
||||
val: ScalarMaybeUninit<Provenance>,
|
||||
index: VectorIdx,
|
||||
thread_clock: &VClock,
|
||||
is_seqcst: bool,
|
||||
@ -408,7 +409,11 @@ impl StoreElement {
|
||||
/// buffer regardless of subsequent loads by the same thread; if the earliest load of another
|
||||
/// thread doesn't happen before the current one, then no subsequent load by the other thread
|
||||
/// can happen before the current one.
|
||||
fn load_impl(&self, index: VectorIdx, clocks: &ThreadClockSet) -> ScalarMaybeUninit<Tag> {
|
||||
fn load_impl(
|
||||
&self,
|
||||
index: VectorIdx,
|
||||
clocks: &ThreadClockSet,
|
||||
) -> ScalarMaybeUninit<Provenance> {
|
||||
let _ = self.loads.borrow_mut().try_insert(index, clocks.clock[index]);
|
||||
self.val
|
||||
}
|
||||
@ -421,7 +426,10 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>:
|
||||
// If weak memory emulation is enabled, check if this atomic op imperfectly overlaps with a previous
|
||||
// atomic read or write. If it does, then we require it to be ordered (non-racy) with all previous atomic
|
||||
// accesses on all the bytes in range
|
||||
fn validate_overlapping_atomic(&self, place: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn validate_overlapping_atomic(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
|
||||
if let crate::AllocExtra {
|
||||
@ -448,10 +456,10 @@ fn validate_overlapping_atomic(&self, place: &MPlaceTy<'tcx, Tag>) -> InterpResu
|
||||
|
||||
fn buffered_atomic_rmw(
|
||||
&mut self,
|
||||
new_val: ScalarMaybeUninit<Tag>,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
new_val: ScalarMaybeUninit<Provenance>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicRwOrd,
|
||||
init: ScalarMaybeUninit<Tag>,
|
||||
init: ScalarMaybeUninit<Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
|
||||
@ -474,11 +482,11 @@ fn buffered_atomic_rmw(
|
||||
|
||||
fn buffered_atomic_read(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicReadOrd,
|
||||
latest_in_mo: ScalarMaybeUninit<Tag>,
|
||||
latest_in_mo: ScalarMaybeUninit<Provenance>,
|
||||
validate: impl FnOnce() -> InterpResult<'tcx>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
if let Some(global) = &this.machine.data_race {
|
||||
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(place.ptr)?;
|
||||
@ -510,10 +518,10 @@ fn buffered_atomic_read(
|
||||
|
||||
fn buffered_atomic_write(
|
||||
&mut self,
|
||||
val: ScalarMaybeUninit<Tag>,
|
||||
dest: &MPlaceTy<'tcx, Tag>,
|
||||
val: ScalarMaybeUninit<Provenance>,
|
||||
dest: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicWriteOrd,
|
||||
init: ScalarMaybeUninit<Tag>,
|
||||
init: ScalarMaybeUninit<Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let (alloc_id, base_offset, ..) = this.ptr_get_alloc_id(dest.ptr)?;
|
||||
@ -555,9 +563,9 @@ fn buffered_atomic_write(
|
||||
/// to perform load_impl on the latest store element
|
||||
fn perform_read_on_buffered_latest(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicReadOrd,
|
||||
init: ScalarMaybeUninit<Tag>,
|
||||
init: ScalarMaybeUninit<Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_ref();
|
||||
|
||||
|
@ -65,7 +65,7 @@ pub enum NonHaltingDiagnostic {
|
||||
CreatedPointerTag(NonZeroU64, Option<(AllocId, AllocRange)>),
|
||||
/// This `Item` was popped from the borrow stack, either due to an access with the given tag or
|
||||
/// a deallocation when the second argument is `None`.
|
||||
PoppedPointerTag(Item, Option<(SbTagExtra, AccessKind)>),
|
||||
PoppedPointerTag(Item, Option<(ProvenanceExtra, AccessKind)>),
|
||||
CreatedCallId(CallId),
|
||||
CreatedAlloc(AllocId, Size, Align, MemoryKind<MiriMemoryKind>),
|
||||
FreedAlloc(AllocId),
|
||||
|
@ -165,7 +165,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
||||
entry_id: DefId,
|
||||
entry_type: EntryFnType,
|
||||
config: &MiriConfig,
|
||||
) -> InterpResult<'tcx, (InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>, MPlaceTy<'tcx, Tag>)> {
|
||||
) -> InterpResult<'tcx, (InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>, MPlaceTy<'tcx, Provenance>)> {
|
||||
let param_env = ty::ParamEnv::reveal_all();
|
||||
let layout_cx = LayoutCx { tcx, param_env };
|
||||
let mut ecx = InterpCx::new(
|
||||
@ -202,7 +202,7 @@ pub fn create_ecx<'mir, 'tcx: 'mir>(
|
||||
// Third argument (`argv`): created from `config.args`.
|
||||
let argv = {
|
||||
// Put each argument in memory, collect pointers.
|
||||
let mut argvs = Vec::<Immediate<Tag>>::new();
|
||||
let mut argvs = Vec::<Immediate<Provenance>>::new();
|
||||
for arg in config.args.iter() {
|
||||
// Make space for `0` terminator.
|
||||
let size = u64::try_from(arg.len()).unwrap().checked_add(1).unwrap();
|
||||
|
105
src/helpers.rs
105
src/helpers.rs
@ -84,7 +84,7 @@ fn resolve_path(&self, path: &[&str]) -> ty::Instance<'tcx> {
|
||||
|
||||
/// Evaluates the scalar at the specified path. Returns Some(val)
|
||||
/// if the path could be resolved, and None otherwise
|
||||
fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let instance = this.resolve_path(path);
|
||||
let cid = GlobalId { instance, promoted: None };
|
||||
@ -94,7 +94,7 @@ fn eval_path_scalar(&self, path: &[&str]) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
}
|
||||
|
||||
/// Helper function to get a `libc` constant as a `Scalar`.
|
||||
fn eval_libc(&self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn eval_libc(&self, name: &str) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
self.eval_path_scalar(&["libc", name])
|
||||
}
|
||||
|
||||
@ -105,7 +105,7 @@ fn eval_libc_i32(&self, name: &str) -> InterpResult<'tcx, i32> {
|
||||
}
|
||||
|
||||
/// Helper function to get a `windows` constant as a `Scalar`.
|
||||
fn eval_windows(&self, module: &str, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn eval_windows(&self, module: &str, name: &str) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
self.eval_context_ref().eval_path_scalar(&["std", "sys", "windows", module, name])
|
||||
}
|
||||
|
||||
@ -134,9 +134,9 @@ fn windows_ty_layout(&self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>>
|
||||
/// Project to the given *named* field of the mplace (which must be a struct or union type).
|
||||
fn mplace_field_named(
|
||||
&self,
|
||||
mplace: &MPlaceTy<'tcx, Tag>,
|
||||
mplace: &MPlaceTy<'tcx, Provenance>,
|
||||
name: &str,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Tag>> {
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let adt = mplace.layout.ty.ty_adt_def().unwrap();
|
||||
for (idx, field) in adt.non_enum_variant().fields.iter().enumerate() {
|
||||
@ -150,7 +150,11 @@ fn mplace_field_named(
|
||||
/// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned,
|
||||
/// we try to do the right thing anyway. `i128` can fit all integer types except for `u128` so
|
||||
/// this method is fine for almost all integer types.
|
||||
fn write_int(&mut self, i: impl Into<i128>, dest: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn write_int(
|
||||
&mut self,
|
||||
i: impl Into<i128>,
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
assert!(dest.layout.abi.is_scalar(), "write_int on non-scalar type {}", dest.layout.ty);
|
||||
let val = if dest.layout.abi.is_signed() {
|
||||
Scalar::from_int(i, dest.layout.size)
|
||||
@ -164,7 +168,7 @@ fn write_int(&mut self, i: impl Into<i128>, dest: &PlaceTy<'tcx, Tag>) -> Interp
|
||||
fn write_int_fields(
|
||||
&mut self,
|
||||
values: &[i128],
|
||||
dest: &MPlaceTy<'tcx, Tag>,
|
||||
dest: &MPlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
for (idx, &val) in values.iter().enumerate() {
|
||||
@ -178,7 +182,7 @@ fn write_int_fields(
|
||||
fn write_int_fields_named(
|
||||
&mut self,
|
||||
values: &[(&str, i128)],
|
||||
dest: &MPlaceTy<'tcx, Tag>,
|
||||
dest: &MPlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
for &(name, val) in values.iter() {
|
||||
@ -189,24 +193,24 @@ fn write_int_fields_named(
|
||||
}
|
||||
|
||||
/// Write a 0 of the appropriate size to `dest`.
|
||||
fn write_null(&mut self, dest: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn write_null(&mut self, dest: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
self.write_int(0, dest)
|
||||
}
|
||||
|
||||
/// Test if this pointer equals 0.
|
||||
fn ptr_is_null(&self, ptr: Pointer<Option<Tag>>) -> InterpResult<'tcx, bool> {
|
||||
fn ptr_is_null(&self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, bool> {
|
||||
Ok(ptr.addr().bytes() == 0)
|
||||
}
|
||||
|
||||
/// Get the `Place` for a local
|
||||
fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
|
||||
fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
let place = mir::Place { local, projection: List::empty() };
|
||||
this.eval_place(place)
|
||||
}
|
||||
|
||||
/// Generate some random bytes, and write them to `dest`.
|
||||
fn gen_random(&mut self, ptr: Pointer<Option<Tag>>, len: u64) -> InterpResult<'tcx> {
|
||||
fn gen_random(&mut self, ptr: Pointer<Option<Provenance>>, len: u64) -> InterpResult<'tcx> {
|
||||
// Some programs pass in a null pointer and a length of 0
|
||||
// to their platform's random-generation function (e.g. getrandom())
|
||||
// on Linux. For compatibility with these programs, we don't perform
|
||||
@ -240,8 +244,8 @@ fn call_function(
|
||||
&mut self,
|
||||
f: ty::Instance<'tcx>,
|
||||
caller_abi: Abi,
|
||||
args: &[Immediate<Tag>],
|
||||
dest: Option<&PlaceTy<'tcx, Tag>>,
|
||||
args: &[Immediate<Provenance>],
|
||||
dest: Option<&PlaceTy<'tcx, Provenance>>,
|
||||
stack_pop: StackPopCleanup,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -285,7 +289,7 @@ fn call_function(
|
||||
/// The range is relative to `place`.
|
||||
fn visit_freeze_sensitive(
|
||||
&self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
size: Size,
|
||||
mut action: impl FnMut(AllocRange, bool) -> InterpResult<'tcx>,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -304,7 +308,7 @@ fn visit_freeze_sensitive(
|
||||
let mut cur_addr = start_addr;
|
||||
// Called when we detected an `UnsafeCell` at the given offset and size.
|
||||
// Calls `action` and advances `cur_ptr`.
|
||||
let mut unsafe_cell_action = |unsafe_cell_ptr: &Pointer<Option<Tag>>,
|
||||
let mut unsafe_cell_action = |unsafe_cell_ptr: &Pointer<Option<Provenance>>,
|
||||
unsafe_cell_size: Size| {
|
||||
// We assume that we are given the fields in increasing offset order,
|
||||
// and nothing else changes.
|
||||
@ -359,7 +363,7 @@ fn visit_freeze_sensitive(
|
||||
/// whether we are inside an `UnsafeCell` or not.
|
||||
struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
|
||||
where
|
||||
F: FnMut(&MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>,
|
||||
F: FnMut(&MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx>,
|
||||
{
|
||||
ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
|
||||
unsafe_cell_action: F,
|
||||
@ -368,9 +372,9 @@ struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
|
||||
impl<'ecx, 'mir, 'tcx: 'mir, F> ValueVisitor<'mir, 'tcx, Evaluator<'mir, 'tcx>>
|
||||
for UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
|
||||
where
|
||||
F: FnMut(&MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>,
|
||||
F: FnMut(&MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx>,
|
||||
{
|
||||
type V = MPlaceTy<'tcx, Tag>;
|
||||
type V = MPlaceTy<'tcx, Provenance>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
|
||||
@ -378,7 +382,7 @@ fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
// Hook to detect `UnsafeCell`.
|
||||
fn visit_value(&mut self, v: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn visit_value(&mut self, v: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
|
||||
let is_unsafe_cell = match v.layout.ty.kind() {
|
||||
ty::Adt(adt, _) =>
|
||||
@ -421,8 +425,8 @@ fn visit_value(&mut self, v: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
// Make sure we visit aggregrates in increasing offset order.
|
||||
fn visit_aggregate(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
fields: impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
fields: impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Provenance>>>,
|
||||
) -> InterpResult<'tcx> {
|
||||
match place.layout.fields {
|
||||
FieldsShape::Array { .. } => {
|
||||
@ -432,8 +436,8 @@ fn visit_aggregate(
|
||||
}
|
||||
FieldsShape::Arbitrary { .. } => {
|
||||
// Gather the subplaces and sort them before visiting.
|
||||
let mut places =
|
||||
fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
|
||||
let mut places = fields
|
||||
.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Provenance>>>>()?;
|
||||
// we just compare offsets, the abs. value never matters
|
||||
places.sort_by_key(|place| place.ptr.addr());
|
||||
self.walk_aggregate(place, places.into_iter().map(Ok))
|
||||
@ -447,7 +451,7 @@ fn visit_aggregate(
|
||||
|
||||
fn visit_union(
|
||||
&mut self,
|
||||
_v: &MPlaceTy<'tcx, Tag>,
|
||||
_v: &MPlaceTy<'tcx, Provenance>,
|
||||
_fields: NonZeroUsize,
|
||||
) -> InterpResult<'tcx> {
|
||||
bug!("we should have already handled unions in `visit_value`")
|
||||
@ -511,7 +515,7 @@ fn assert_target_os_is_unix(&self, name: &str) {
|
||||
|
||||
/// Get last error variable as a place, lazily allocating thread-local storage for it if
|
||||
/// necessary.
|
||||
fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx, Tag>> {
|
||||
fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
if let Some(errno_place) = this.active_thread_ref().last_error {
|
||||
Ok(errno_place)
|
||||
@ -526,14 +530,14 @@ fn last_error_place(&mut self) -> InterpResult<'tcx, MPlaceTy<'tcx, Tag>> {
|
||||
}
|
||||
|
||||
/// Sets the last error variable.
|
||||
fn set_last_error(&mut self, scalar: Scalar<Tag>) -> InterpResult<'tcx> {
|
||||
fn set_last_error(&mut self, scalar: Scalar<Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let errno_place = this.last_error_place()?;
|
||||
this.write_scalar(scalar, &errno_place.into())
|
||||
}
|
||||
|
||||
/// Gets the last error variable.
|
||||
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
let errno_place = this.last_error_place()?;
|
||||
this.read_scalar(&errno_place.into())?.check_init()
|
||||
@ -541,7 +545,10 @@ fn get_last_error(&mut self) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
|
||||
/// This function tries to produce the most similar OS error from the `std::io::ErrorKind`
|
||||
/// as a platform-specific errnum.
|
||||
fn io_error_to_errnum(&self, err_kind: std::io::ErrorKind) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn io_error_to_errnum(
|
||||
&self,
|
||||
err_kind: std::io::ErrorKind,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let target = &this.tcx.sess.target;
|
||||
if target.families.iter().any(|f| f == "unix") {
|
||||
@ -575,7 +582,10 @@ fn io_error_to_errnum(&self, err_kind: std::io::ErrorKind) -> InterpResult<'tcx,
|
||||
}
|
||||
|
||||
/// The inverse of `io_error_to_errnum`.
|
||||
fn errnum_to_io_error(&self, errnum: Scalar<Tag>) -> InterpResult<'tcx, std::io::ErrorKind> {
|
||||
fn errnum_to_io_error(
|
||||
&self,
|
||||
errnum: Scalar<Provenance>,
|
||||
) -> InterpResult<'tcx, std::io::ErrorKind> {
|
||||
let this = self.eval_context_ref();
|
||||
let target = &this.tcx.sess.target;
|
||||
if target.families.iter().any(|f| f == "unix") {
|
||||
@ -621,10 +631,10 @@ fn try_unwrap_io_result<T: From<i32>>(
|
||||
/// Calculates the MPlaceTy given the offset and layout of an access on an operand
|
||||
fn deref_operand_and_offset(
|
||||
&self,
|
||||
op: &OpTy<'tcx, Tag>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Tag>> {
|
||||
) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let op_place = this.deref_operand(op)?;
|
||||
let offset = Size::from_bytes(offset);
|
||||
@ -637,10 +647,10 @@ fn deref_operand_and_offset(
|
||||
|
||||
fn read_scalar_at_offset(
|
||||
&self,
|
||||
op: &OpTy<'tcx, Tag>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
let this = self.eval_context_ref();
|
||||
let value_place = this.deref_operand_and_offset(op, offset, layout)?;
|
||||
this.read_scalar(&value_place.into())
|
||||
@ -648,9 +658,9 @@ fn read_scalar_at_offset(
|
||||
|
||||
fn write_scalar_at_offset(
|
||||
&mut self,
|
||||
op: &OpTy<'tcx, Tag>,
|
||||
op: &OpTy<'tcx, Provenance>,
|
||||
offset: u64,
|
||||
value: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
value: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
layout: TyAndLayout<'tcx>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -661,7 +671,10 @@ fn write_scalar_at_offset(
|
||||
/// Parse a `timespec` struct and return it as a `std::time::Duration`. It returns `None`
|
||||
/// if the value in the `timespec` struct is invalid. Some libc functions will return
|
||||
/// `EINVAL` in this case.
|
||||
fn read_timespec(&mut self, tp: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx, Option<Duration>> {
|
||||
fn read_timespec(
|
||||
&mut self,
|
||||
tp: &MPlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Option<Duration>> {
|
||||
let this = self.eval_context_mut();
|
||||
let seconds_place = this.mplace_field(tp, 0)?;
|
||||
let seconds_scalar = this.read_scalar(&seconds_place.into())?;
|
||||
@ -683,7 +696,7 @@ fn read_timespec(&mut self, tp: &MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx, Opti
|
||||
})
|
||||
}
|
||||
|
||||
fn read_c_str<'a>(&'a self, ptr: Pointer<Option<Tag>>) -> InterpResult<'tcx, &'a [u8]>
|
||||
fn read_c_str<'a>(&'a self, ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, &'a [u8]>
|
||||
where
|
||||
'tcx: 'a,
|
||||
'mir: 'a,
|
||||
@ -709,7 +722,7 @@ fn read_c_str<'a>(&'a self, ptr: Pointer<Option<Tag>>) -> InterpResult<'tcx, &'a
|
||||
this.read_bytes_ptr(ptr, len)
|
||||
}
|
||||
|
||||
fn read_wide_str(&self, mut ptr: Pointer<Option<Tag>>) -> InterpResult<'tcx, Vec<u16>> {
|
||||
fn read_wide_str(&self, mut ptr: Pointer<Option<Provenance>>) -> InterpResult<'tcx, Vec<u16>> {
|
||||
let this = self.eval_context_ref();
|
||||
let size2 = Size::from_bytes(2);
|
||||
let align2 = Align::from_bytes(2).unwrap();
|
||||
@ -801,17 +814,17 @@ fn check_shim<'a, const N: usize>(
|
||||
abi: Abi,
|
||||
exp_abi: Abi,
|
||||
link_name: Symbol,
|
||||
args: &'a [OpTy<'tcx, Tag>],
|
||||
) -> InterpResult<'tcx, &'a [OpTy<'tcx, Tag>; N]>
|
||||
args: &'a [OpTy<'tcx, Provenance>],
|
||||
) -> InterpResult<'tcx, &'a [OpTy<'tcx, Provenance>; N]>
|
||||
where
|
||||
&'a [OpTy<'tcx, Tag>; N]: TryFrom<&'a [OpTy<'tcx, Tag>]>,
|
||||
&'a [OpTy<'tcx, Provenance>; N]: TryFrom<&'a [OpTy<'tcx, Provenance>]>,
|
||||
{
|
||||
self.check_abi_and_shim_symbol_clash(abi, exp_abi, link_name)?;
|
||||
check_arg_count(args)
|
||||
}
|
||||
|
||||
/// Mark a machine allocation that was just created as immutable.
|
||||
fn mark_immutable(&mut self, mplace: &MemPlace<Tag>) {
|
||||
fn mark_immutable(&mut self, mplace: &MemPlace<Provenance>) {
|
||||
let this = self.eval_context_mut();
|
||||
// This got just allocated, so there definitely is a pointer here.
|
||||
let provenance = mplace.ptr.into_pointer_or_addr().unwrap().provenance;
|
||||
@ -866,10 +879,10 @@ fn current_span(machine: &Evaluator<'_, '_>) -> Span {
|
||||
|
||||
/// Check that the number of args is what we expect.
|
||||
pub fn check_arg_count<'a, 'tcx, const N: usize>(
|
||||
args: &'a [OpTy<'tcx, Tag>],
|
||||
) -> InterpResult<'tcx, &'a [OpTy<'tcx, Tag>; N]>
|
||||
args: &'a [OpTy<'tcx, Provenance>],
|
||||
) -> InterpResult<'tcx, &'a [OpTy<'tcx, Provenance>; N]>
|
||||
where
|
||||
&'a [OpTy<'tcx, Tag>; N]: TryFrom<&'a [OpTy<'tcx, Tag>]>,
|
||||
&'a [OpTy<'tcx, Provenance>; N]: TryFrom<&'a [OpTy<'tcx, Provenance>]>,
|
||||
{
|
||||
if let Ok(ops) = args.try_into() {
|
||||
return Ok(ops);
|
||||
|
@ -109,7 +109,7 @@ pub fn expose_ptr(ecx: &mut MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId, sb:
|
||||
pub fn ptr_from_addr_transmute(
|
||||
_ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
addr: u64,
|
||||
) -> Pointer<Option<Tag>> {
|
||||
) -> Pointer<Option<Provenance>> {
|
||||
trace!("Transmuting {:#x} to a pointer", addr);
|
||||
|
||||
// We consider transmuted pointers to be "invalid" (`None` provenance).
|
||||
@ -119,7 +119,7 @@ pub fn ptr_from_addr_transmute(
|
||||
pub fn ptr_from_addr_cast(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
addr: u64,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
trace!("Casting {:#x} to a pointer", addr);
|
||||
|
||||
let global_state = ecx.machine.intptrcast.borrow();
|
||||
@ -146,7 +146,7 @@ pub fn ptr_from_addr_cast(
|
||||
}
|
||||
|
||||
// This is how wildcard pointers are born.
|
||||
Ok(Pointer::new(Some(Tag::Wildcard), Size::from_bytes(addr)))
|
||||
Ok(Pointer::new(Some(Provenance::Wildcard), Size::from_bytes(addr)))
|
||||
}
|
||||
|
||||
fn alloc_base_addr(ecx: &MiriEvalContext<'mir, 'tcx>, alloc_id: AllocId) -> u64 {
|
||||
@ -208,11 +208,11 @@ pub fn rel_ptr_to_addr(ecx: &MiriEvalContext<'mir, 'tcx>, ptr: Pointer<AllocId>)
|
||||
/// access is going.
|
||||
pub fn abs_ptr_to_rel(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
ptr: Pointer<Tag>,
|
||||
ptr: Pointer<Provenance>,
|
||||
) -> Option<(AllocId, Size)> {
|
||||
let (tag, addr) = ptr.into_parts(); // addr is absolute (Tag provenance)
|
||||
|
||||
let alloc_id = if let Tag::Concrete { alloc_id, .. } = tag {
|
||||
let alloc_id = if let Provenance::Concrete { alloc_id, .. } = tag {
|
||||
alloc_id
|
||||
} else {
|
||||
// A wildcard pointer.
|
||||
|
@ -57,7 +57,7 @@
|
||||
// Make all those symbols available in the same place as our own.
|
||||
pub use rustc_const_eval::interpret::*;
|
||||
// Resolve ambiguity.
|
||||
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy};
|
||||
pub use rustc_const_eval::interpret::{self, AllocMap, PlaceTy, Provenance as _};
|
||||
|
||||
pub use crate::shims::dlsym::{Dlsym, EvalContextExt as _};
|
||||
pub use crate::shims::env::{EnvVars, EvalContextExt as _};
|
||||
@ -83,15 +83,14 @@
|
||||
pub use crate::helpers::{CurrentSpan, EvalContextExt as HelpersEvalContextExt};
|
||||
pub use crate::intptrcast::ProvenanceMode;
|
||||
pub use crate::machine::{
|
||||
AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind, Tag,
|
||||
NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
|
||||
AllocExtra, Evaluator, FrameData, MiriEvalContext, MiriEvalContextExt, MiriMemoryKind,
|
||||
Provenance, ProvenanceExtra, NUM_CPUS, PAGE_SIZE, STACK_ADDR, STACK_SIZE,
|
||||
};
|
||||
pub use crate::mono_hash_map::MonoHashMap;
|
||||
pub use crate::operator::EvalContextExt as OperatorEvalContextExt;
|
||||
pub use crate::range_map::RangeMap;
|
||||
pub use crate::stacked_borrows::{
|
||||
CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, SbTagExtra, Stack,
|
||||
Stacks,
|
||||
CallId, EvalContextExt as StackedBorEvalContextExt, Item, Permission, SbTag, Stack, Stacks,
|
||||
};
|
||||
pub use crate::sync::{CondvarId, EvalContextExt as SyncEvalContextExt, MutexId, RwLockId};
|
||||
pub use crate::thread::{
|
||||
|
151
src/machine.rs
151
src/machine.rs
@ -126,9 +126,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
/// Pointer provenance (tag).
|
||||
/// Pointer provenance.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum Tag {
|
||||
pub enum Provenance {
|
||||
Concrete {
|
||||
alloc_id: AllocId,
|
||||
/// Stacked Borrows tag.
|
||||
@ -137,27 +137,34 @@ pub enum Tag {
|
||||
Wildcard,
|
||||
}
|
||||
|
||||
/// The "extra" information a pointer has over a regular AllocId.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum ProvenanceExtra {
|
||||
Concrete(SbTag),
|
||||
Wildcard,
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
static_assert_size!(Pointer<Tag>, 24);
|
||||
static_assert_size!(Pointer<Provenance>, 24);
|
||||
// FIXME: this would with in 24bytes but layout optimizations are not smart enough
|
||||
// #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
//static_assert_size!(Pointer<Option<Tag>>, 24);
|
||||
//static_assert_size!(Pointer<Option<Provenance>>, 24);
|
||||
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
|
||||
static_assert_size!(ScalarMaybeUninit<Tag>, 32);
|
||||
static_assert_size!(ScalarMaybeUninit<Provenance>, 32);
|
||||
|
||||
impl Provenance for Tag {
|
||||
/// We use absolute addresses in the `offset` of a `Pointer<Tag>`.
|
||||
impl interpret::Provenance for Provenance {
|
||||
/// We use absolute addresses in the `offset` of a `Pointer<Provenance>`.
|
||||
const OFFSET_IS_ADDR: bool = true;
|
||||
|
||||
/// We cannot err on partial overwrites, it happens too often in practice (due to unions).
|
||||
const ERR_ON_PARTIAL_PTR_OVERWRITE: bool = false;
|
||||
|
||||
fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let (tag, addr) = ptr.into_parts(); // address is absolute
|
||||
let (prov, addr) = ptr.into_parts(); // address is absolute
|
||||
write!(f, "{:#x}", addr.bytes())?;
|
||||
|
||||
match tag {
|
||||
Tag::Concrete { alloc_id, sb } => {
|
||||
match prov {
|
||||
Provenance::Concrete { alloc_id, sb } => {
|
||||
// Forward `alternate` flag to `alloc_id` printing.
|
||||
if f.alternate() {
|
||||
write!(f, "[{:#?}]", alloc_id)?;
|
||||
@ -167,7 +174,7 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Print Stacked Borrows tag.
|
||||
write!(f, "{:?}", sb)?;
|
||||
}
|
||||
Tag::Wildcard => {
|
||||
Provenance::Wildcard => {
|
||||
write!(f, "[wildcard]")?;
|
||||
}
|
||||
}
|
||||
@ -177,8 +184,26 @@ fn fmt(ptr: &Pointer<Self>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
||||
fn get_alloc_id(self) -> Option<AllocId> {
|
||||
match self {
|
||||
Tag::Concrete { alloc_id, .. } => Some(alloc_id),
|
||||
Tag::Wildcard => None,
|
||||
Provenance::Concrete { alloc_id, .. } => Some(alloc_id),
|
||||
Provenance::Wildcard => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ProvenanceExtra {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
ProvenanceExtra::Concrete(pid) => write!(f, "{pid:?}"),
|
||||
ProvenanceExtra::Wildcard => write!(f, "<wildcard>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ProvenanceExtra {
|
||||
pub fn and_then<T>(self, f: impl FnOnce(SbTag) -> Option<T>) -> Option<T> {
|
||||
match self {
|
||||
ProvenanceExtra::Concrete(pid) => f(pid),
|
||||
ProvenanceExtra::Wildcard => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -244,9 +269,9 @@ pub struct Evaluator<'mir, 'tcx> {
|
||||
/// Program arguments (`Option` because we can only initialize them after creating the ecx).
|
||||
/// These are *pointers* to argc/argv because macOS.
|
||||
/// We also need the full command line as one string because of Windows.
|
||||
pub(crate) argc: Option<MemPlace<Tag>>,
|
||||
pub(crate) argv: Option<MemPlace<Tag>>,
|
||||
pub(crate) cmd_line: Option<MemPlace<Tag>>,
|
||||
pub(crate) argc: Option<MemPlace<Provenance>>,
|
||||
pub(crate) argv: Option<MemPlace<Provenance>>,
|
||||
pub(crate) cmd_line: Option<MemPlace<Provenance>>,
|
||||
|
||||
/// TLS state.
|
||||
pub(crate) tls: TlsData<'tcx>,
|
||||
@ -302,7 +327,7 @@ pub struct Evaluator<'mir, 'tcx> {
|
||||
pub(crate) local_crates: Vec<CrateNum>,
|
||||
|
||||
/// Mapping extern static names to their base pointer.
|
||||
extern_statics: FxHashMap<Symbol, Pointer<Tag>>,
|
||||
extern_statics: FxHashMap<Symbol, Pointer<Provenance>>,
|
||||
|
||||
/// The random number generator used for resolving non-determinism.
|
||||
/// Needs to be queried by ptr_to_int, hence needs interior mutability.
|
||||
@ -403,7 +428,7 @@ pub(crate) fn late_init(
|
||||
fn add_extern_static(
|
||||
this: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
name: &str,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
) {
|
||||
// This got just allocated, so there definitely is a pointer here.
|
||||
let ptr = ptr.into_pointer_or_addr().unwrap();
|
||||
@ -491,11 +516,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'mir, 'tcx> {
|
||||
type FrameExtra = FrameData<'tcx>;
|
||||
type AllocExtra = AllocExtra;
|
||||
|
||||
type PointerTag = Tag;
|
||||
type TagExtra = SbTagExtra;
|
||||
type Provenance = Provenance;
|
||||
type ProvenanceExtra = ProvenanceExtra;
|
||||
|
||||
type MemoryMap =
|
||||
MonoHashMap<AllocId, (MemoryKind<MiriMemoryKind>, Allocation<Tag, Self::AllocExtra>)>;
|
||||
type MemoryMap = MonoHashMap<
|
||||
AllocId,
|
||||
(MemoryKind<MiriMemoryKind>, Allocation<Provenance, Self::AllocExtra>),
|
||||
>;
|
||||
|
||||
const GLOBAL_KIND: Option<MiriMemoryKind> = Some(MiriMemoryKind::Global);
|
||||
|
||||
@ -541,8 +568,8 @@ fn find_mir_or_eval_fn(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
@ -554,8 +581,8 @@ fn call_extra_fn(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
fn_val: Dlsym,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
_unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -566,8 +593,8 @@ fn call_extra_fn(
|
||||
fn call_intrinsic(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -592,23 +619,23 @@ fn abort(_ecx: &mut MiriEvalContext<'mir, 'tcx>, msg: String) -> InterpResult<'t
|
||||
fn binary_ptr_op(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
bin_op: mir::BinOp,
|
||||
left: &ImmTy<'tcx, Tag>,
|
||||
right: &ImmTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, (Scalar<Tag>, bool, ty::Ty<'tcx>)> {
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, (Scalar<Provenance>, bool, ty::Ty<'tcx>)> {
|
||||
ecx.binary_ptr_op(bin_op, left, right)
|
||||
}
|
||||
|
||||
fn thread_local_static_base_pointer(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
def_id: DefId,
|
||||
) -> InterpResult<'tcx, Pointer<Tag>> {
|
||||
) -> InterpResult<'tcx, Pointer<Provenance>> {
|
||||
ecx.get_or_create_thread_local_alloc(def_id)
|
||||
}
|
||||
|
||||
fn extern_static_base_pointer(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
def_id: DefId,
|
||||
) -> InterpResult<'tcx, Pointer<Tag>> {
|
||||
) -> InterpResult<'tcx, Pointer<Provenance>> {
|
||||
let link_name = ecx.item_link_name(def_id);
|
||||
if let Some(&ptr) = ecx.machine.extern_statics.get(&link_name) {
|
||||
Ok(ptr)
|
||||
@ -621,12 +648,12 @@ fn extern_static_base_pointer(
|
||||
}
|
||||
}
|
||||
|
||||
fn init_allocation_extra<'b>(
|
||||
fn adjust_allocation<'b>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
id: AllocId,
|
||||
alloc: Cow<'b, Allocation>,
|
||||
kind: Option<MemoryKind<Self::MemoryKind>>,
|
||||
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>> {
|
||||
) -> InterpResult<'tcx, Cow<'b, Allocation<Self::Provenance, Self::AllocExtra>>> {
|
||||
let kind = kind.expect("we set our STATIC_KIND so this cannot be None");
|
||||
if ecx.machine.tracked_alloc_ids.contains(&id) {
|
||||
register_diagnostic(NonHaltingDiagnostic::CreatedAlloc(
|
||||
@ -664,7 +691,7 @@ fn init_allocation_extra<'b>(
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let alloc: Allocation<Tag, Self::AllocExtra> = alloc.convert_tag_add_extra(
|
||||
let alloc: Allocation<Provenance, Self::AllocExtra> = alloc.adjust_from_tcx(
|
||||
&ecx.tcx,
|
||||
AllocExtra {
|
||||
stacked_borrows: stacks.map(RefCell::new),
|
||||
@ -676,19 +703,19 @@ fn init_allocation_extra<'b>(
|
||||
Ok(Cow::Owned(alloc))
|
||||
}
|
||||
|
||||
fn tag_alloc_base_pointer(
|
||||
fn adjust_alloc_base_pointer(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
ptr: Pointer<AllocId>,
|
||||
) -> Pointer<Tag> {
|
||||
) -> Pointer<Provenance> {
|
||||
if cfg!(debug_assertions) {
|
||||
// The machine promises to never call us on thread-local or extern statics.
|
||||
let alloc_id = ptr.provenance;
|
||||
match ecx.tcx.get_global_alloc(alloc_id) {
|
||||
Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_thread_local_static(def_id) => {
|
||||
panic!("tag_alloc_base_pointer called on thread-local static")
|
||||
panic!("adjust_alloc_base_pointer called on thread-local static")
|
||||
}
|
||||
Some(GlobalAlloc::Static(def_id)) if ecx.tcx.is_foreign_item(def_id) => {
|
||||
panic!("tag_alloc_base_pointer called on extern static")
|
||||
panic!("adjust_alloc_base_pointer called on extern static")
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@ -701,7 +728,7 @@ fn tag_alloc_base_pointer(
|
||||
SbTag::default()
|
||||
};
|
||||
Pointer::new(
|
||||
Tag::Concrete { alloc_id: ptr.provenance, sb: sb_tag },
|
||||
Provenance::Concrete { alloc_id: ptr.provenance, sb: sb_tag },
|
||||
Size::from_bytes(absolute_addr),
|
||||
)
|
||||
}
|
||||
@ -710,7 +737,7 @@ fn tag_alloc_base_pointer(
|
||||
fn ptr_from_addr_cast(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
addr: u64,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Self::PointerTag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Self::Provenance>>> {
|
||||
intptrcast::GlobalStateInner::ptr_from_addr_cast(ecx, addr)
|
||||
}
|
||||
|
||||
@ -718,19 +745,19 @@ fn ptr_from_addr_cast(
|
||||
fn ptr_from_addr_transmute(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
addr: u64,
|
||||
) -> Pointer<Option<Self::PointerTag>> {
|
||||
) -> Pointer<Option<Self::Provenance>> {
|
||||
intptrcast::GlobalStateInner::ptr_from_addr_transmute(ecx, addr)
|
||||
}
|
||||
|
||||
fn expose_ptr(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
ptr: Pointer<Self::PointerTag>,
|
||||
ptr: Pointer<Self::Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
match ptr.provenance {
|
||||
Tag::Concrete { alloc_id, sb } => {
|
||||
Provenance::Concrete { alloc_id, sb } => {
|
||||
intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, sb);
|
||||
}
|
||||
Tag::Wildcard => {
|
||||
Provenance::Wildcard => {
|
||||
// No need to do anything for wildcard pointers as
|
||||
// their provenances have already been previously exposed.
|
||||
}
|
||||
@ -742,14 +769,14 @@ fn expose_ptr(
|
||||
/// or a `None` with an absolute address if that conversion is not possible.
|
||||
fn ptr_get_alloc(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
ptr: Pointer<Self::PointerTag>,
|
||||
) -> Option<(AllocId, Size, Self::TagExtra)> {
|
||||
ptr: Pointer<Self::Provenance>,
|
||||
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
|
||||
let rel = intptrcast::GlobalStateInner::abs_ptr_to_rel(ecx, ptr);
|
||||
|
||||
rel.map(|(alloc_id, size)| {
|
||||
let sb = match ptr.provenance {
|
||||
Tag::Concrete { sb, .. } => SbTagExtra::Concrete(sb),
|
||||
Tag::Wildcard => SbTagExtra::Wildcard,
|
||||
Provenance::Concrete { sb, .. } => ProvenanceExtra::Concrete(sb),
|
||||
Provenance::Wildcard => ProvenanceExtra::Wildcard,
|
||||
};
|
||||
(alloc_id, size, sb)
|
||||
})
|
||||
@ -760,7 +787,7 @@ fn memory_read(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
machine: &Self,
|
||||
alloc_extra: &AllocExtra,
|
||||
(alloc_id, tag): (AllocId, Self::TagExtra),
|
||||
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
|
||||
range: AllocRange,
|
||||
) -> InterpResult<'tcx> {
|
||||
if let Some(data_race) = &alloc_extra.data_race {
|
||||
@ -774,7 +801,7 @@ fn memory_read(
|
||||
if let Some(stacked_borrows) = &alloc_extra.stacked_borrows {
|
||||
stacked_borrows.borrow_mut().memory_read(
|
||||
alloc_id,
|
||||
tag,
|
||||
prov_extra,
|
||||
range,
|
||||
machine.stacked_borrows.as_ref().unwrap(),
|
||||
machine.current_span(),
|
||||
@ -792,7 +819,7 @@ fn memory_written(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
machine: &mut Self,
|
||||
alloc_extra: &mut AllocExtra,
|
||||
(alloc_id, tag): (AllocId, Self::TagExtra),
|
||||
(alloc_id, prov_extra): (AllocId, Self::ProvenanceExtra),
|
||||
range: AllocRange,
|
||||
) -> InterpResult<'tcx> {
|
||||
if let Some(data_race) = &mut alloc_extra.data_race {
|
||||
@ -806,7 +833,7 @@ fn memory_written(
|
||||
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
|
||||
stacked_borrows.get_mut().memory_written(
|
||||
alloc_id,
|
||||
tag,
|
||||
prov_extra,
|
||||
range,
|
||||
machine.stacked_borrows.as_ref().unwrap(),
|
||||
machine.current_span(),
|
||||
@ -824,7 +851,7 @@ fn memory_deallocated(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
machine: &mut Self,
|
||||
alloc_extra: &mut AllocExtra,
|
||||
(alloc_id, tag): (AllocId, Self::TagExtra),
|
||||
(alloc_id, prove_extra): (AllocId, Self::ProvenanceExtra),
|
||||
range: AllocRange,
|
||||
) -> InterpResult<'tcx> {
|
||||
if machine.tracked_alloc_ids.contains(&alloc_id) {
|
||||
@ -841,7 +868,7 @@ fn memory_deallocated(
|
||||
if let Some(stacked_borrows) = &mut alloc_extra.stacked_borrows {
|
||||
stacked_borrows.get_mut().memory_deallocated(
|
||||
alloc_id,
|
||||
tag,
|
||||
prove_extra,
|
||||
range,
|
||||
machine.stacked_borrows.as_ref().unwrap(),
|
||||
&machine.threads,
|
||||
@ -855,7 +882,7 @@ fn memory_deallocated(
|
||||
fn retag(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
kind: mir::RetagKind,
|
||||
place: &PlaceTy<'tcx, Tag>,
|
||||
place: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
if ecx.machine.stacked_borrows.is_some() { ecx.retag(kind, place) } else { Ok(()) }
|
||||
}
|
||||
@ -863,8 +890,8 @@ fn retag(
|
||||
#[inline(always)]
|
||||
fn init_frame_extra(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
frame: Frame<'mir, 'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Tag, FrameData<'tcx>>> {
|
||||
frame: Frame<'mir, 'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>> {
|
||||
// Start recording our event before doing anything else
|
||||
let timing = if let Some(profiler) = ecx.machine.profiler.as_ref() {
|
||||
let fn_name = frame.instance.to_string();
|
||||
@ -892,13 +919,13 @@ fn init_frame_extra(
|
||||
|
||||
fn stack<'a>(
|
||||
ecx: &'a InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a [Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>] {
|
||||
) -> &'a [Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>] {
|
||||
ecx.active_thread_stack()
|
||||
}
|
||||
|
||||
fn stack_mut<'a>(
|
||||
ecx: &'a mut InterpCx<'mir, 'tcx, Self>,
|
||||
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>> {
|
||||
) -> &'a mut Vec<Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> {
|
||||
ecx.active_thread_stack_mut()
|
||||
}
|
||||
|
||||
@ -925,7 +952,7 @@ fn after_stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>
|
||||
#[inline(always)]
|
||||
fn after_stack_pop(
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Self>,
|
||||
mut frame: Frame<'mir, 'tcx, Tag, FrameData<'tcx>>,
|
||||
mut frame: Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>,
|
||||
unwinding: bool,
|
||||
) -> InterpResult<'tcx, StackPopJump> {
|
||||
let timing = frame.extra.timing.take();
|
||||
|
@ -9,18 +9,18 @@ pub trait EvalContextExt<'tcx> {
|
||||
fn binary_ptr_op(
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
left: &ImmTy<'tcx, Tag>,
|
||||
right: &ImmTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)>;
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, (Scalar<Provenance>, bool, Ty<'tcx>)>;
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> EvalContextExt<'tcx> for super::MiriEvalContext<'mir, 'tcx> {
|
||||
fn binary_ptr_op(
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
left: &ImmTy<'tcx, Tag>,
|
||||
right: &ImmTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)> {
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, (Scalar<Provenance>, bool, Ty<'tcx>)> {
|
||||
use rustc_middle::mir::BinOp::*;
|
||||
|
||||
trace!("ptr_op: {:?} {:?} {:?}", *left, bin_op, *right);
|
||||
|
@ -11,8 +11,8 @@ fn handle_miri_backtrace_size(
|
||||
&mut self,
|
||||
abi: Abi,
|
||||
link_name: Symbol,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let [flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
||||
@ -31,8 +31,8 @@ fn handle_miri_get_backtrace(
|
||||
&mut self,
|
||||
abi: Abi,
|
||||
link_name: Symbol,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let tcx = this.tcx;
|
||||
@ -117,7 +117,7 @@ fn handle_miri_get_backtrace(
|
||||
|
||||
fn resolve_frame_pointer(
|
||||
&mut self,
|
||||
ptr: &OpTy<'tcx, Tag>,
|
||||
ptr: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, (Instance<'tcx>, Loc, String, String)> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -145,8 +145,8 @@ fn handle_miri_resolve_frame(
|
||||
&mut self,
|
||||
abi: Abi,
|
||||
link_name: Symbol,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let [ptr, flags] = this.check_shim(abi, Abi::Rust, link_name, args)?;
|
||||
@ -228,7 +228,7 @@ fn handle_miri_resolve_frame_names(
|
||||
&mut self,
|
||||
abi: Abi,
|
||||
link_name: Symbol,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
@ -33,8 +33,8 @@ fn call_dlsym(
|
||||
&mut self,
|
||||
dlsym: Dlsym,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -30,10 +30,10 @@ fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 {
|
||||
pub struct EnvVars<'tcx> {
|
||||
/// Stores pointers to the environment variables. These variables must be stored as
|
||||
/// null-terminated target strings (c_str or wide_str) with the `"{name}={value}"` format.
|
||||
map: FxHashMap<OsString, Pointer<Option<Tag>>>,
|
||||
map: FxHashMap<OsString, Pointer<Option<Provenance>>>,
|
||||
|
||||
/// Place where the `environ` static is stored. Lazily initialized, but then never changes.
|
||||
pub(crate) environ: Option<MPlaceTy<'tcx, Tag>>,
|
||||
pub(crate) environ: Option<MPlaceTy<'tcx, Provenance>>,
|
||||
}
|
||||
|
||||
impl<'tcx> EnvVars<'tcx> {
|
||||
@ -92,7 +92,7 @@ fn alloc_env_var_as_c_str<'mir, 'tcx>(
|
||||
name: &OsStr,
|
||||
value: &OsStr,
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let mut name_osstring = name.to_os_string();
|
||||
name_osstring.push("=");
|
||||
name_osstring.push(value);
|
||||
@ -103,7 +103,7 @@ fn alloc_env_var_as_wide_str<'mir, 'tcx>(
|
||||
name: &OsStr,
|
||||
value: &OsStr,
|
||||
ecx: &mut InterpCx<'mir, 'tcx, Evaluator<'mir, 'tcx>>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let mut name_osstring = name.to_os_string();
|
||||
name_osstring.push("=");
|
||||
name_osstring.push(value);
|
||||
@ -112,7 +112,10 @@ fn alloc_env_var_as_wide_str<'mir, 'tcx>(
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn getenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
fn getenv(
|
||||
&mut self,
|
||||
name_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("getenv");
|
||||
|
||||
@ -133,9 +136,9 @@ fn getenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Pointer<Op
|
||||
#[allow(non_snake_case)]
|
||||
fn GetEnvironmentVariableW(
|
||||
&mut self,
|
||||
name_op: &OpTy<'tcx, Tag>, // LPCWSTR
|
||||
buf_op: &OpTy<'tcx, Tag>, // LPWSTR
|
||||
size_op: &OpTy<'tcx, Tag>, // DWORD
|
||||
name_op: &OpTy<'tcx, Provenance>, // LPCWSTR
|
||||
buf_op: &OpTy<'tcx, Provenance>, // LPWSTR
|
||||
size_op: &OpTy<'tcx, Provenance>, // DWORD
|
||||
) -> InterpResult<'tcx, u32> {
|
||||
// ^ Returns DWORD (u32 on Windows)
|
||||
|
||||
@ -168,7 +171,7 @@ fn GetEnvironmentVariableW(
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn GetEnvironmentStringsW(&mut self) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
fn GetEnvironmentStringsW(&mut self) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("windows", "GetEnvironmentStringsW");
|
||||
|
||||
@ -191,7 +194,7 @@ fn GetEnvironmentStringsW(&mut self) -> InterpResult<'tcx, Pointer<Option<Tag>>>
|
||||
#[allow(non_snake_case)]
|
||||
fn FreeEnvironmentStringsW(
|
||||
&mut self,
|
||||
env_block_op: &OpTy<'tcx, Tag>,
|
||||
env_block_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("windows", "FreeEnvironmentStringsW");
|
||||
@ -204,8 +207,8 @@ fn FreeEnvironmentStringsW(
|
||||
|
||||
fn setenv(
|
||||
&mut self,
|
||||
name_op: &OpTy<'tcx, Tag>,
|
||||
value_op: &OpTy<'tcx, Tag>,
|
||||
name_op: &OpTy<'tcx, Provenance>,
|
||||
value_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("setenv");
|
||||
@ -239,8 +242,8 @@ fn setenv(
|
||||
#[allow(non_snake_case)]
|
||||
fn SetEnvironmentVariableW(
|
||||
&mut self,
|
||||
name_op: &OpTy<'tcx, Tag>, // LPCWSTR
|
||||
value_op: &OpTy<'tcx, Tag>, // LPCWSTR
|
||||
name_op: &OpTy<'tcx, Provenance>, // LPCWSTR
|
||||
value_op: &OpTy<'tcx, Provenance>, // LPCWSTR
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("windows", "SetEnvironmentVariableW");
|
||||
@ -276,7 +279,7 @@ fn SetEnvironmentVariableW(
|
||||
}
|
||||
}
|
||||
|
||||
fn unsetenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn unsetenv(&mut self, name_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("unsetenv");
|
||||
|
||||
@ -304,9 +307,9 @@ fn unsetenv(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
|
||||
fn getcwd(
|
||||
&mut self,
|
||||
buf_op: &OpTy<'tcx, Tag>,
|
||||
size_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
buf_op: &OpTy<'tcx, Provenance>,
|
||||
size_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("getcwd");
|
||||
|
||||
@ -337,8 +340,8 @@ fn getcwd(
|
||||
#[allow(non_snake_case)]
|
||||
fn GetCurrentDirectoryW(
|
||||
&mut self,
|
||||
size_op: &OpTy<'tcx, Tag>, // DWORD
|
||||
buf_op: &OpTy<'tcx, Tag>, // LPTSTR
|
||||
size_op: &OpTy<'tcx, Provenance>, // DWORD
|
||||
buf_op: &OpTy<'tcx, Provenance>, // LPTSTR
|
||||
) -> InterpResult<'tcx, u32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("windows", "GetCurrentDirectoryW");
|
||||
@ -361,7 +364,7 @@ fn GetCurrentDirectoryW(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn chdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn chdir(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os_is_unix("chdir");
|
||||
|
||||
@ -386,7 +389,7 @@ fn chdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
#[allow(non_snake_case)]
|
||||
fn SetCurrentDirectoryW(
|
||||
&mut self,
|
||||
path_op: &OpTy<'tcx, Tag>, // LPCTSTR
|
||||
path_op: &OpTy<'tcx, Provenance>, // LPCTSTR
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
// ^ Returns BOOL (i32 on Windows)
|
||||
|
||||
@ -428,7 +431,7 @@ fn update_environ(&mut self) -> InterpResult<'tcx> {
|
||||
}
|
||||
|
||||
// Collect all the pointers to each variable in a vector.
|
||||
let mut vars: Vec<Pointer<Option<Tag>>> =
|
||||
let mut vars: Vec<Pointer<Option<Provenance>>> =
|
||||
this.machine.env_vars.map.values().copied().collect();
|
||||
// Add the trailing null pointer.
|
||||
vars.push(Pointer::null());
|
||||
|
@ -74,7 +74,7 @@ fn malloc(
|
||||
size: u64,
|
||||
zero_init: bool,
|
||||
kind: MiriMemoryKind,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let this = self.eval_context_mut();
|
||||
if size == 0 {
|
||||
Ok(Pointer::null())
|
||||
@ -89,7 +89,11 @@ fn malloc(
|
||||
}
|
||||
}
|
||||
|
||||
fn free(&mut self, ptr: Pointer<Option<Tag>>, kind: MiriMemoryKind) -> InterpResult<'tcx> {
|
||||
fn free(
|
||||
&mut self,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
kind: MiriMemoryKind,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
if !this.ptr_is_null(ptr)? {
|
||||
this.deallocate_ptr(ptr, None, kind.into())?;
|
||||
@ -99,10 +103,10 @@ fn free(&mut self, ptr: Pointer<Option<Tag>>, kind: MiriMemoryKind) -> InterpRes
|
||||
|
||||
fn realloc(
|
||||
&mut self,
|
||||
old_ptr: Pointer<Option<Tag>>,
|
||||
old_ptr: Pointer<Option<Provenance>>,
|
||||
new_size: u64,
|
||||
kind: MiriMemoryKind,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let this = self.eval_context_mut();
|
||||
let new_align = this.min_align(new_size, kind);
|
||||
if this.ptr_is_null(old_ptr)? {
|
||||
@ -231,8 +235,8 @@ fn emulate_foreign_item(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
@ -353,8 +357,8 @@ fn emulate_foreign_item_by_name(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
@ -18,8 +18,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn emulate_atomic_intrinsic(
|
||||
&mut self,
|
||||
intrinsic_name: &str,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -121,8 +121,8 @@ fn fence_ord<'tcx>(ord: &str) -> InterpResult<'tcx, AtomicFenceOrd> {
|
||||
|
||||
fn atomic_load(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicReadOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -150,7 +150,7 @@ fn atomic_load(
|
||||
|
||||
fn atomic_store(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
atomic: AtomicWriteOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -177,7 +177,7 @@ fn atomic_store(
|
||||
|
||||
fn compiler_fence(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
atomic: AtomicFenceOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let [] = check_arg_count(args)?;
|
||||
@ -188,7 +188,7 @@ fn compiler_fence(
|
||||
|
||||
fn atomic_fence(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
atomic: AtomicFenceOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -199,8 +199,8 @@ fn atomic_fence(
|
||||
|
||||
fn atomic_op(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
atomic_op: AtomicOp,
|
||||
atomic: AtomicRwOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -252,8 +252,8 @@ fn atomic_op(
|
||||
|
||||
fn atomic_exchange(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
atomic: AtomicRwOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -280,8 +280,8 @@ fn atomic_exchange(
|
||||
|
||||
fn atomic_compare_exchange_impl(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
success: AtomicRwOrd,
|
||||
fail: AtomicReadOrd,
|
||||
can_fail_spuriously: bool,
|
||||
@ -320,8 +320,8 @@ fn atomic_compare_exchange_impl(
|
||||
|
||||
fn atomic_compare_exchange(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
success: AtomicRwOrd,
|
||||
fail: AtomicReadOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -330,8 +330,8 @@ fn atomic_compare_exchange(
|
||||
|
||||
fn atomic_compare_exchange_weak(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
success: AtomicRwOrd,
|
||||
fail: AtomicReadOrd,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
@ -20,8 +20,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn call_intrinsic(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
_unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -58,8 +58,8 @@ fn call_intrinsic(
|
||||
fn emulate_intrinsic_by_name(
|
||||
&mut self,
|
||||
intrinsic_name: &str,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -375,9 +375,9 @@ fn float_to_int_unchecked<F>(
|
||||
&self,
|
||||
f: F,
|
||||
dest_ty: ty::Ty<'tcx>,
|
||||
) -> InterpResult<'tcx, Scalar<Tag>>
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>>
|
||||
where
|
||||
F: Float + Into<Scalar<Tag>>,
|
||||
F: Float + Into<Scalar<Provenance>>,
|
||||
{
|
||||
let this = self.eval_context_ref();
|
||||
|
||||
|
@ -12,8 +12,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn emulate_simd_intrinsic(
|
||||
&mut self,
|
||||
intrinsic_name: &str,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
match intrinsic_name {
|
||||
@ -557,13 +557,13 @@ enum Op {
|
||||
}
|
||||
}
|
||||
|
||||
fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Tag> {
|
||||
fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Provenance> {
|
||||
// SIMD uses all-1 as pattern for "true"
|
||||
let val = if b { -1 } else { 0 };
|
||||
Scalar::from_int(val, size)
|
||||
}
|
||||
|
||||
fn simd_element_to_bool(elem: ImmTy<'_, Tag>) -> InterpResult<'_, bool> {
|
||||
fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<'_, bool> {
|
||||
let val = elem.to_scalar()?.to_int(elem.layout.size)?;
|
||||
Ok(match val {
|
||||
0 => false,
|
||||
@ -581,9 +581,9 @@ fn simd_bitmask_index(idx: u64, vec_len: u64, endianess: Endian) -> u64 {
|
||||
}
|
||||
|
||||
fn fmax_op<'tcx>(
|
||||
left: &ImmTy<'tcx, Tag>,
|
||||
right: &ImmTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
assert_eq!(left.layout.ty, right.layout.ty);
|
||||
let ty::Float(float_ty) = left.layout.ty.kind() else {
|
||||
bug!("fmax operand is not a float")
|
||||
@ -597,9 +597,9 @@ fn fmax_op<'tcx>(
|
||||
}
|
||||
|
||||
fn fmin_op<'tcx>(
|
||||
left: &ImmTy<'tcx, Tag>,
|
||||
right: &ImmTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
left: &ImmTy<'tcx, Provenance>,
|
||||
right: &ImmTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
assert_eq!(left.layout.ty, right.layout.ty);
|
||||
let ty::Float(float_ty) = left.layout.ty.kind() else {
|
||||
bug!("fmin operand is not a float")
|
||||
|
@ -27,8 +27,8 @@ fn find_mir_or_eval_fn(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
|
||||
@ -62,9 +62,9 @@ fn find_mir_or_eval_fn(
|
||||
/// the actual MIR of `align_offset`.
|
||||
fn align_offset(
|
||||
&mut self,
|
||||
ptr_op: &OpTy<'tcx, Tag>,
|
||||
align_op: &OpTy<'tcx, Tag>,
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
ptr_op: &OpTy<'tcx, Provenance>,
|
||||
align_op: &OpTy<'tcx, Provenance>,
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx, bool> {
|
||||
|
@ -52,7 +52,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
/// the Unix APIs usually handle.
|
||||
fn read_os_str_from_c_str<'a>(
|
||||
&'a self,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
) -> InterpResult<'tcx, &'a OsStr>
|
||||
where
|
||||
'tcx: 'a,
|
||||
@ -67,7 +67,7 @@ fn read_os_str_from_c_str<'a>(
|
||||
/// which is what the Windows APIs usually handle.
|
||||
fn read_os_str_from_wide_str<'a>(
|
||||
&'a self,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
) -> InterpResult<'tcx, OsString>
|
||||
where
|
||||
'tcx: 'a,
|
||||
@ -96,7 +96,7 @@ pub fn u16vec_to_osstring<'tcx>(u16_vec: Vec<u16>) -> InterpResult<'tcx, OsStrin
|
||||
fn write_os_str_to_c_str(
|
||||
&mut self,
|
||||
os_str: &OsStr,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
size: u64,
|
||||
) -> InterpResult<'tcx, (bool, u64)> {
|
||||
let bytes = os_str_to_bytes(os_str)?;
|
||||
@ -119,7 +119,7 @@ fn write_os_str_to_c_str(
|
||||
fn write_os_str_to_wide_str(
|
||||
&mut self,
|
||||
os_str: &OsStr,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
size: u64,
|
||||
) -> InterpResult<'tcx, (bool, u64)> {
|
||||
#[cfg(windows)]
|
||||
@ -165,7 +165,7 @@ fn alloc_os_str_as_c_str(
|
||||
&mut self,
|
||||
os_str: &OsStr,
|
||||
memkind: MemoryKind<MiriMemoryKind>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0` terminator.
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -180,7 +180,7 @@ fn alloc_os_str_as_wide_str(
|
||||
&mut self,
|
||||
os_str: &OsStr,
|
||||
memkind: MemoryKind<MiriMemoryKind>,
|
||||
) -> InterpResult<'tcx, Pointer<Option<Tag>>> {
|
||||
) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
|
||||
let size = u64::try_from(os_str.len()).unwrap().checked_add(1).unwrap(); // Make space for `0x0000` terminator.
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -193,7 +193,7 @@ fn alloc_os_str_as_wide_str(
|
||||
/// Read a null-terminated sequence of bytes, and perform path separator conversion if needed.
|
||||
fn read_path_from_c_str<'a>(
|
||||
&'a self,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
) -> InterpResult<'tcx, Cow<'a, Path>>
|
||||
where
|
||||
'tcx: 'a,
|
||||
@ -209,7 +209,10 @@ fn read_path_from_c_str<'a>(
|
||||
}
|
||||
|
||||
/// Read a null-terminated sequence of `u16`s, and perform path separator conversion if needed.
|
||||
fn read_path_from_wide_str(&self, ptr: Pointer<Option<Tag>>) -> InterpResult<'tcx, PathBuf> {
|
||||
fn read_path_from_wide_str(
|
||||
&self,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
) -> InterpResult<'tcx, PathBuf> {
|
||||
let this = self.eval_context_ref();
|
||||
let os_str = this.read_os_str_from_wide_str(ptr)?;
|
||||
|
||||
@ -224,7 +227,7 @@ fn read_path_from_wide_str(&self, ptr: Pointer<Option<Tag>>) -> InterpResult<'tc
|
||||
fn write_path_to_c_str(
|
||||
&mut self,
|
||||
path: &Path,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
size: u64,
|
||||
) -> InterpResult<'tcx, (bool, u64)> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -238,7 +241,7 @@ fn write_path_to_c_str(
|
||||
fn write_path_to_wide_str(
|
||||
&mut self,
|
||||
path: &Path,
|
||||
ptr: Pointer<Option<Tag>>,
|
||||
ptr: Pointer<Option<Provenance>>,
|
||||
size: u64,
|
||||
) -> InterpResult<'tcx, (bool, u64)> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -26,11 +26,11 @@
|
||||
#[derive(Debug)]
|
||||
pub struct CatchUnwindData<'tcx> {
|
||||
/// The `catch_fn` callback to call in case of a panic.
|
||||
catch_fn: Scalar<Tag>,
|
||||
catch_fn: Scalar<Provenance>,
|
||||
/// The `data` argument for that callback.
|
||||
data: Scalar<Tag>,
|
||||
data: Scalar<Provenance>,
|
||||
/// The return place from the original call to `try`.
|
||||
dest: PlaceTy<'tcx, Tag>,
|
||||
dest: PlaceTy<'tcx, Provenance>,
|
||||
/// The return block from the original call to `try`.
|
||||
ret: mir::BasicBlock,
|
||||
}
|
||||
@ -43,7 +43,7 @@ fn handle_miri_start_panic(
|
||||
&mut self,
|
||||
abi: Abi,
|
||||
link_name: Symbol,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
unwind: StackPopUnwind,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
@ -65,8 +65,8 @@ fn handle_miri_start_panic(
|
||||
/// Handles the `try` intrinsic, the underlying implementation of `std::panicking::try`.
|
||||
fn handle_try(
|
||||
&mut self,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: mir::BasicBlock,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -13,8 +13,8 @@ impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mi
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn clock_gettime(
|
||||
&mut self,
|
||||
clk_id_op: &OpTy<'tcx, Tag>,
|
||||
tp_op: &OpTy<'tcx, Tag>,
|
||||
clk_id_op: &OpTy<'tcx, Provenance>,
|
||||
tp_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
// This clock support is deliberately minimal because a lot of clock types have fiddly
|
||||
// properties (is it possible for Miri to be suspended independently of the host?). If you
|
||||
@ -59,8 +59,8 @@ fn clock_gettime(
|
||||
|
||||
fn gettimeofday(
|
||||
&mut self,
|
||||
tv_op: &OpTy<'tcx, Tag>,
|
||||
tz_op: &OpTy<'tcx, Tag>,
|
||||
tv_op: &OpTy<'tcx, Provenance>,
|
||||
tz_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -85,7 +85,10 @@ fn gettimeofday(
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn GetSystemTimeAsFileTime(
|
||||
&mut self,
|
||||
LPFILETIME_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.assert_target_os("windows", "GetSystemTimeAsFileTime");
|
||||
@ -115,7 +118,7 @@ fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: &OpTy<'tcx, Tag>) -> Interp
|
||||
#[allow(non_snake_case)]
|
||||
fn QueryPerformanceCounter(
|
||||
&mut self,
|
||||
lpPerformanceCount_op: &OpTy<'tcx, Tag>,
|
||||
lpPerformanceCount_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -138,7 +141,7 @@ fn QueryPerformanceCounter(
|
||||
#[allow(non_snake_case)]
|
||||
fn QueryPerformanceFrequency(
|
||||
&mut self,
|
||||
lpFrequency_op: &OpTy<'tcx, Tag>,
|
||||
lpFrequency_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -172,7 +175,7 @@ fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
|
||||
})
|
||||
}
|
||||
|
||||
fn mach_timebase_info(&mut self, info_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn mach_timebase_info(&mut self, info_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.assert_target_os("macos", "mach_timebase_info");
|
||||
@ -190,8 +193,8 @@ fn mach_timebase_info(&mut self, info_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx
|
||||
|
||||
fn nanosleep(
|
||||
&mut self,
|
||||
req_op: &OpTy<'tcx, Tag>,
|
||||
_rem: &OpTy<'tcx, Tag>,
|
||||
req_op: &OpTy<'tcx, Provenance>,
|
||||
_rem: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
// Signal handlers are not supported, so rem will never be written to.
|
||||
|
||||
|
@ -19,7 +19,7 @@
|
||||
pub struct TlsEntry<'tcx> {
|
||||
/// The data for this key. None is used to represent NULL.
|
||||
/// (We normalize this early to avoid having to do a NULL-ptr-test each time we access the data.)
|
||||
data: BTreeMap<ThreadId, Scalar<Tag>>,
|
||||
data: BTreeMap<ThreadId, Scalar<Provenance>>,
|
||||
dtor: Option<ty::Instance<'tcx>>,
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ pub struct TlsData<'tcx> {
|
||||
|
||||
/// A single per thread destructor of the thread local storage (that's how
|
||||
/// things work on macOS) with a data argument.
|
||||
macos_thread_dtors: BTreeMap<ThreadId, (ty::Instance<'tcx>, Scalar<Tag>)>,
|
||||
macos_thread_dtors: BTreeMap<ThreadId, (ty::Instance<'tcx>, Scalar<Provenance>)>,
|
||||
|
||||
/// State for currently running TLS dtors. If this map contains a key for a
|
||||
/// specific thread, it means that we are in the "destruct" phase, during
|
||||
@ -94,7 +94,7 @@ pub fn load_tls(
|
||||
key: TlsKey,
|
||||
thread_id: ThreadId,
|
||||
cx: &impl HasDataLayout,
|
||||
) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
match self.keys.get(&key) {
|
||||
Some(TlsEntry { data, .. }) => {
|
||||
let value = data.get(&thread_id).copied();
|
||||
@ -109,7 +109,7 @@ pub fn store_tls(
|
||||
&mut self,
|
||||
key: TlsKey,
|
||||
thread_id: ThreadId,
|
||||
new_data: Scalar<Tag>,
|
||||
new_data: Scalar<Provenance>,
|
||||
cx: &impl HasDataLayout,
|
||||
) -> InterpResult<'tcx> {
|
||||
match self.keys.get_mut(&key) {
|
||||
@ -140,7 +140,7 @@ pub fn set_macos_thread_dtor(
|
||||
&mut self,
|
||||
thread: ThreadId,
|
||||
dtor: ty::Instance<'tcx>,
|
||||
data: Scalar<Tag>,
|
||||
data: Scalar<Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
if self.dtors_running.contains_key(&thread) {
|
||||
// UB, according to libstd docs.
|
||||
@ -179,7 +179,7 @@ fn fetch_tls_dtor(
|
||||
&mut self,
|
||||
key: Option<TlsKey>,
|
||||
thread_id: ThreadId,
|
||||
) -> Option<(ty::Instance<'tcx>, Scalar<Tag>, TlsKey)> {
|
||||
) -> Option<(ty::Instance<'tcx>, Scalar<Provenance>, TlsKey)> {
|
||||
use std::ops::Bound::*;
|
||||
|
||||
let thread_local = &mut self.keys;
|
||||
|
@ -32,8 +32,8 @@ fn call_dlsym(
|
||||
&mut self,
|
||||
dlsym: Dlsym,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -19,8 +19,8 @@ fn emulate_foreign_item_by_name(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
@ -19,8 +19,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn call_dlsym(
|
||||
&mut self,
|
||||
dlsym: Dlsym,
|
||||
_args: &[OpTy<'tcx, Tag>],
|
||||
_dest: &PlaceTy<'tcx, Tag>,
|
||||
_args: &[OpTy<'tcx, Provenance>],
|
||||
_dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -11,8 +11,8 @@ fn emulate_foreign_item_by_name(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||
let this = self.eval_context_mut();
|
||||
match link_name.as_str() {
|
||||
|
@ -386,7 +386,7 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, '
|
||||
fn macos_stat_write_buf(
|
||||
&mut self,
|
||||
metadata: FileMetadata,
|
||||
buf_op: &OpTy<'tcx, Tag>,
|
||||
buf_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -493,7 +493,7 @@ pub struct OpenDir {
|
||||
/// The directory reader on the host.
|
||||
read_dir: ReadDir,
|
||||
/// The most recent entry returned by readdir()
|
||||
entry: Pointer<Option<Tag>>,
|
||||
entry: Pointer<Option<Provenance>>,
|
||||
}
|
||||
|
||||
impl OpenDir {
|
||||
@ -556,7 +556,7 @@ fn maybe_sync_file(
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn open(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
|
||||
fn open(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
|
||||
if args.len() < 2 {
|
||||
throw_ub_format!(
|
||||
"incorrect number of arguments for `open`: got {}, expected at least 2",
|
||||
@ -667,7 +667,7 @@ fn open(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
|
||||
this.try_unwrap_io_result(fd)
|
||||
}
|
||||
|
||||
fn fcntl(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
|
||||
fn fcntl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
if args.len() < 2 {
|
||||
@ -741,7 +741,7 @@ fn fcntl(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
|
||||
}
|
||||
}
|
||||
|
||||
fn close(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn close(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let fd = this.read_scalar(fd_op)?.to_i32()?;
|
||||
@ -754,7 +754,12 @@ fn close(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
}
|
||||
}
|
||||
|
||||
fn read(&mut self, fd: i32, buf: Pointer<Option<Tag>>, count: u64) -> InterpResult<'tcx, i64> {
|
||||
fn read(
|
||||
&mut self,
|
||||
fd: i32,
|
||||
buf: Pointer<Option<Provenance>>,
|
||||
count: u64,
|
||||
) -> InterpResult<'tcx, i64> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// Isolation check is done via `FileDescriptor` trait.
|
||||
@ -802,7 +807,12 @@ fn read(&mut self, fd: i32, buf: Pointer<Option<Tag>>, count: u64) -> InterpResu
|
||||
}
|
||||
}
|
||||
|
||||
fn write(&mut self, fd: i32, buf: Pointer<Option<Tag>>, count: u64) -> InterpResult<'tcx, i64> {
|
||||
fn write(
|
||||
&mut self,
|
||||
fd: i32,
|
||||
buf: Pointer<Option<Provenance>>,
|
||||
count: u64,
|
||||
) -> InterpResult<'tcx, i64> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// Isolation check is done via `FileDescriptor` trait.
|
||||
@ -832,9 +842,9 @@ fn write(&mut self, fd: i32, buf: Pointer<Option<Tag>>, count: u64) -> InterpRes
|
||||
|
||||
fn lseek64(
|
||||
&mut self,
|
||||
fd_op: &OpTy<'tcx, Tag>,
|
||||
offset_op: &OpTy<'tcx, Tag>,
|
||||
whence_op: &OpTy<'tcx, Tag>,
|
||||
fd_op: &OpTy<'tcx, Provenance>,
|
||||
offset_op: &OpTy<'tcx, Provenance>,
|
||||
whence_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i64> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -867,7 +877,7 @@ fn lseek64(
|
||||
}
|
||||
}
|
||||
|
||||
fn unlink(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn unlink(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
|
||||
@ -885,8 +895,8 @@ fn unlink(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
|
||||
fn symlink(
|
||||
&mut self,
|
||||
target_op: &OpTy<'tcx, Tag>,
|
||||
linkpath_op: &OpTy<'tcx, Tag>,
|
||||
target_op: &OpTy<'tcx, Provenance>,
|
||||
linkpath_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
#[cfg(unix)]
|
||||
fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||
@ -916,8 +926,8 @@ fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> {
|
||||
|
||||
fn macos_stat(
|
||||
&mut self,
|
||||
path_op: &OpTy<'tcx, Tag>,
|
||||
buf_op: &OpTy<'tcx, Tag>,
|
||||
path_op: &OpTy<'tcx, Provenance>,
|
||||
buf_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("macos", "stat");
|
||||
@ -945,8 +955,8 @@ fn macos_stat(
|
||||
// `lstat` is used to get symlink metadata.
|
||||
fn macos_lstat(
|
||||
&mut self,
|
||||
path_op: &OpTy<'tcx, Tag>,
|
||||
buf_op: &OpTy<'tcx, Tag>,
|
||||
path_op: &OpTy<'tcx, Provenance>,
|
||||
buf_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("macos", "lstat");
|
||||
@ -972,8 +982,8 @@ fn macos_lstat(
|
||||
|
||||
fn macos_fstat(
|
||||
&mut self,
|
||||
fd_op: &OpTy<'tcx, Tag>,
|
||||
buf_op: &OpTy<'tcx, Tag>,
|
||||
fd_op: &OpTy<'tcx, Provenance>,
|
||||
buf_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -997,11 +1007,11 @@ fn macos_fstat(
|
||||
|
||||
fn linux_statx(
|
||||
&mut self,
|
||||
dirfd_op: &OpTy<'tcx, Tag>, // Should be an `int`
|
||||
pathname_op: &OpTy<'tcx, Tag>, // Should be a `const char *`
|
||||
flags_op: &OpTy<'tcx, Tag>, // Should be an `int`
|
||||
mask_op: &OpTy<'tcx, Tag>, // Should be an `unsigned int`
|
||||
statxbuf_op: &OpTy<'tcx, Tag>, // Should be a `struct statx *`
|
||||
dirfd_op: &OpTy<'tcx, Provenance>, // Should be an `int`
|
||||
pathname_op: &OpTy<'tcx, Provenance>, // Should be a `const char *`
|
||||
flags_op: &OpTy<'tcx, Provenance>, // Should be an `int`
|
||||
mask_op: &OpTy<'tcx, Provenance>, // Should be an `unsigned int`
|
||||
statxbuf_op: &OpTy<'tcx, Provenance>, // Should be a `struct statx *`
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1188,8 +1198,8 @@ fn linux_statx(
|
||||
|
||||
fn rename(
|
||||
&mut self,
|
||||
oldpath_op: &OpTy<'tcx, Tag>,
|
||||
newpath_op: &OpTy<'tcx, Tag>,
|
||||
oldpath_op: &OpTy<'tcx, Provenance>,
|
||||
newpath_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1219,8 +1229,8 @@ fn rename(
|
||||
|
||||
fn mkdir(
|
||||
&mut self,
|
||||
path_op: &OpTy<'tcx, Tag>,
|
||||
mode_op: &OpTy<'tcx, Tag>,
|
||||
path_op: &OpTy<'tcx, Provenance>,
|
||||
mode_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1256,7 +1266,7 @@ fn mkdir(
|
||||
this.try_unwrap_io_result(result)
|
||||
}
|
||||
|
||||
fn rmdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn rmdir(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let path = this.read_path_from_c_str(this.read_pointer(path_op)?)?;
|
||||
@ -1273,7 +1283,10 @@ fn rmdir(&mut self, path_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
this.try_unwrap_io_result(result)
|
||||
}
|
||||
|
||||
fn opendir(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn opendir(
|
||||
&mut self,
|
||||
name_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let name = this.read_path_from_c_str(this.read_pointer(name_op)?)?;
|
||||
@ -1304,7 +1317,10 @@ fn opendir(&mut self, name_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Ta
|
||||
}
|
||||
}
|
||||
|
||||
fn linux_readdir64(&mut self, dirp_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, Scalar<Tag>> {
|
||||
fn linux_readdir64(
|
||||
&mut self,
|
||||
dirp_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, Scalar<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
this.assert_target_os("linux", "readdir64");
|
||||
@ -1393,9 +1409,9 @@ fn linux_readdir64(&mut self, dirp_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, S
|
||||
|
||||
fn macos_readdir_r(
|
||||
&mut self,
|
||||
dirp_op: &OpTy<'tcx, Tag>,
|
||||
entry_op: &OpTy<'tcx, Tag>,
|
||||
result_op: &OpTy<'tcx, Tag>,
|
||||
dirp_op: &OpTy<'tcx, Provenance>,
|
||||
entry_op: &OpTy<'tcx, Provenance>,
|
||||
result_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1490,7 +1506,7 @@ fn macos_readdir_r(
|
||||
}
|
||||
}
|
||||
|
||||
fn closedir(&mut self, dirp_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let dirp = this.read_scalar(dirp_op)?.to_machine_usize(this)?;
|
||||
@ -1513,8 +1529,8 @@ fn closedir(&mut self, dirp_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
|
||||
fn ftruncate64(
|
||||
&mut self,
|
||||
fd_op: &OpTy<'tcx, Tag>,
|
||||
length_op: &OpTy<'tcx, Tag>,
|
||||
fd_op: &OpTy<'tcx, Provenance>,
|
||||
length_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1551,7 +1567,7 @@ fn ftruncate64(
|
||||
}
|
||||
}
|
||||
|
||||
fn fsync(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn fsync(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
// On macOS, `fsync` (unlike `fcntl(F_FULLFSYNC)`) does not wait for the
|
||||
// underlying disk to finish writing. In the interest of host compatibility,
|
||||
// we conservatively implement this with `sync_all`, which
|
||||
@ -1578,7 +1594,7 @@ fn fsync(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
}
|
||||
}
|
||||
|
||||
fn fdatasync(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn fdatasync(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let fd = this.read_scalar(fd_op)?.to_i32()?;
|
||||
@ -1602,10 +1618,10 @@ fn fdatasync(&mut self, fd_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
|
||||
fn sync_file_range(
|
||||
&mut self,
|
||||
fd_op: &OpTy<'tcx, Tag>,
|
||||
offset_op: &OpTy<'tcx, Tag>,
|
||||
nbytes_op: &OpTy<'tcx, Tag>,
|
||||
flags_op: &OpTy<'tcx, Tag>,
|
||||
fd_op: &OpTy<'tcx, Provenance>,
|
||||
offset_op: &OpTy<'tcx, Provenance>,
|
||||
nbytes_op: &OpTy<'tcx, Provenance>,
|
||||
flags_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1647,9 +1663,9 @@ fn sync_file_range(
|
||||
|
||||
fn readlink(
|
||||
&mut self,
|
||||
pathname_op: &OpTy<'tcx, Tag>,
|
||||
buf_op: &OpTy<'tcx, Tag>,
|
||||
bufsize_op: &OpTy<'tcx, Tag>,
|
||||
pathname_op: &OpTy<'tcx, Provenance>,
|
||||
buf_op: &OpTy<'tcx, Provenance>,
|
||||
bufsize_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i64> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -1691,7 +1707,7 @@ fn readlink(
|
||||
}
|
||||
|
||||
#[cfg_attr(not(unix), allow(unused))]
|
||||
fn isatty(&mut self, miri_fd: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn isatty(&mut self, miri_fd: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
#[cfg(unix)]
|
||||
if matches!(this.machine.isolated_op, IsolatedOp::Allow) {
|
||||
@ -1740,7 +1756,7 @@ fn extract_sec_and_nsec<'tcx>(
|
||||
/// Stores a file's metadata in order to avoid code duplication in the different metadata related
|
||||
/// shims.
|
||||
struct FileMetadata {
|
||||
mode: Scalar<Tag>,
|
||||
mode: Scalar<Provenance>,
|
||||
size: u64,
|
||||
created: Option<(u64, u32)>,
|
||||
accessed: Option<(u64, u32)>,
|
||||
|
@ -23,8 +23,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn call_dlsym(
|
||||
&mut self,
|
||||
dlsym: Dlsym,
|
||||
_args: &[OpTy<'tcx, Tag>],
|
||||
_dest: &PlaceTy<'tcx, Tag>,
|
||||
_args: &[OpTy<'tcx, Provenance>],
|
||||
_dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -14,8 +14,8 @@ fn emulate_foreign_item_by_name(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -165,10 +165,10 @@ fn emulate_foreign_item_by_name(
|
||||
// Shims the linux `getrandom` syscall.
|
||||
fn getrandom<'tcx>(
|
||||
this: &mut MiriEvalContext<'_, 'tcx>,
|
||||
ptr: &OpTy<'tcx, Tag>,
|
||||
len: &OpTy<'tcx, Tag>,
|
||||
flags: &OpTy<'tcx, Tag>,
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
ptr: &OpTy<'tcx, Provenance>,
|
||||
len: &OpTy<'tcx, Provenance>,
|
||||
flags: &OpTy<'tcx, Provenance>,
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let ptr = this.read_pointer(ptr)?;
|
||||
let len = this.read_scalar(len)?.to_machine_usize(this)?;
|
||||
|
@ -7,8 +7,8 @@
|
||||
/// `args` is the arguments *after* the syscall number.
|
||||
pub fn futex<'tcx>(
|
||||
this: &mut MiriEvalContext<'_, 'tcx>,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
// The amount of arguments used depends on the type of futex operation.
|
||||
// The full futex syscall takes six arguments (excluding the syscall
|
||||
|
@ -27,8 +27,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn call_dlsym(
|
||||
&mut self,
|
||||
dlsym: Dlsym,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -12,8 +12,8 @@ fn emulate_foreign_item_by_name(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
@ -21,14 +21,14 @@
|
||||
|
||||
fn is_mutex_kind_default<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
kind: Scalar<Tag>,
|
||||
kind: Scalar<Provenance>,
|
||||
) -> InterpResult<'tcx, bool> {
|
||||
Ok(kind == ecx.eval_libc("PTHREAD_MUTEX_DEFAULT")?)
|
||||
}
|
||||
|
||||
fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
kind: Scalar<Tag>,
|
||||
kind: Scalar<Provenance>,
|
||||
) -> InterpResult<'tcx, bool> {
|
||||
let kind = kind.to_i32()?;
|
||||
let mutex_normal_kind = ecx.eval_libc("PTHREAD_MUTEX_NORMAL")?.to_i32()?;
|
||||
@ -37,15 +37,15 @@ fn is_mutex_kind_normal<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn mutexattr_get_kind<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)
|
||||
}
|
||||
|
||||
fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
kind: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
kind: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(attr_op, 0, kind, layout_of_maybe_uninit(ecx.tcx, ecx.tcx.types.i32))
|
||||
}
|
||||
@ -61,8 +61,8 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn mutex_get_kind<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
|
||||
ecx.read_scalar_at_offset_atomic(
|
||||
mutex_op,
|
||||
@ -74,8 +74,8 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn mutex_set_kind<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
kind: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
kind: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
|
||||
ecx.write_scalar_at_offset_atomic(
|
||||
@ -89,15 +89,15 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn mutex_get_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
ecx.read_scalar_at_offset_atomic(mutex_op, 4, ecx.machine.layouts.u32, AtomicReadOrd::Relaxed)
|
||||
}
|
||||
|
||||
fn mutex_set_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
id: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
id: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset_atomic(
|
||||
mutex_op,
|
||||
@ -110,7 +110,7 @@ fn mutex_set_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn mutex_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, MutexId> {
|
||||
let value_place = ecx.deref_operand_and_offset(mutex_op, 4, ecx.machine.layouts.u32)?;
|
||||
|
||||
@ -145,15 +145,15 @@ fn mutex_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn rwlock_get_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
rwlock_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
ecx.read_scalar_at_offset_atomic(rwlock_op, 4, ecx.machine.layouts.u32, AtomicReadOrd::Relaxed)
|
||||
}
|
||||
|
||||
fn rwlock_set_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
rwlock_op: &OpTy<'tcx, Tag>,
|
||||
id: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
id: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset_atomic(
|
||||
rwlock_op,
|
||||
@ -166,7 +166,7 @@ fn rwlock_set_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn rwlock_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
rwlock_op: &OpTy<'tcx, Tag>,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, RwLockId> {
|
||||
let value_place = ecx.deref_operand_and_offset(rwlock_op, 4, ecx.machine.layouts.u32)?;
|
||||
|
||||
@ -200,15 +200,15 @@ fn rwlock_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn condattr_get_clock_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)
|
||||
}
|
||||
|
||||
fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
clock_id: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
clock_id: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(
|
||||
attr_op,
|
||||
@ -229,15 +229,15 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn cond_get_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
ecx.read_scalar_at_offset_atomic(cond_op, 4, ecx.machine.layouts.u32, AtomicReadOrd::Relaxed)
|
||||
}
|
||||
|
||||
fn cond_set_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
id: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
id: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset_atomic(
|
||||
cond_op,
|
||||
@ -250,7 +250,7 @@ fn cond_set_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn cond_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, CondvarId> {
|
||||
let value_place = ecx.deref_operand_and_offset(cond_op, 4, ecx.machine.layouts.u32)?;
|
||||
|
||||
@ -278,15 +278,15 @@ fn cond_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
|
||||
fn cond_get_clock_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &MiriEvalContext<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Provenance>> {
|
||||
ecx.read_scalar_at_offset(cond_op, 8, ecx.machine.layouts.i32)
|
||||
}
|
||||
|
||||
fn cond_set_clock_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
clock_id: impl Into<ScalarMaybeUninit<Tag>>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
clock_id: impl Into<ScalarMaybeUninit<Provenance>>,
|
||||
) -> InterpResult<'tcx, ()> {
|
||||
ecx.write_scalar_at_offset(
|
||||
cond_op,
|
||||
@ -347,7 +347,10 @@ fn release_cond_mutex_and_block<'mir, 'tcx: 'mir>(
|
||||
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_mutexattr_init(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let default_kind = this.eval_libc("PTHREAD_MUTEX_DEFAULT")?;
|
||||
@ -358,8 +361,8 @@ fn pthread_mutexattr_init(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResult<
|
||||
|
||||
fn pthread_mutexattr_settype(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
kind_op: &OpTy<'tcx, Tag>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
kind_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -397,7 +400,10 @@ fn pthread_mutexattr_settype(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_mutexattr_destroy(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// Destroying an uninit pthread_mutexattr is UB, so check to make sure it's not uninit.
|
||||
@ -423,8 +429,8 @@ fn pthread_mutexattr_destroy(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResu
|
||||
|
||||
fn pthread_mutex_init(
|
||||
&mut self,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -443,7 +449,7 @@ fn pthread_mutex_init(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let kind = mutex_get_kind(this, mutex_op)?.check_init()?;
|
||||
@ -480,7 +486,10 @@ fn pthread_mutex_lock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'tc
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_mutex_trylock(
|
||||
&mut self,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let kind = mutex_get_kind(this, mutex_op)?.check_init()?;
|
||||
@ -513,7 +522,10 @@ fn pthread_mutex_trylock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_mutex_unlock(
|
||||
&mut self,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let kind = mutex_get_kind(this, mutex_op)?.check_init()?;
|
||||
@ -545,7 +557,10 @@ fn pthread_mutex_unlock(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_mutex_destroy(
|
||||
&mut self,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = mutex_get_or_create_id(this, mutex_op)?;
|
||||
@ -566,7 +581,10 @@ fn pthread_mutex_destroy(&mut self, mutex_op: &OpTy<'tcx, Tag>) -> InterpResult<
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_rwlock_rdlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_rwlock_rdlock(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = rwlock_get_or_create_id(this, rwlock_op)?;
|
||||
@ -581,7 +599,10 @@ fn pthread_rwlock_rdlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_rwlock_tryrdlock(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = rwlock_get_or_create_id(this, rwlock_op)?;
|
||||
@ -595,7 +616,10 @@ fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpRes
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_rwlock_wrlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_rwlock_wrlock(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = rwlock_get_or_create_id(this, rwlock_op)?;
|
||||
@ -622,7 +646,10 @@ fn pthread_rwlock_wrlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_rwlock_trywrlock(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = rwlock_get_or_create_id(this, rwlock_op)?;
|
||||
@ -636,7 +663,10 @@ fn pthread_rwlock_trywrlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpRes
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_rwlock_unlock(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = rwlock_get_or_create_id(this, rwlock_op)?;
|
||||
@ -652,7 +682,10 @@ fn pthread_rwlock_unlock(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult
|
||||
}
|
||||
}
|
||||
|
||||
fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_rwlock_destroy(
|
||||
&mut self,
|
||||
rwlock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = rwlock_get_or_create_id(this, rwlock_op)?;
|
||||
@ -671,7 +704,10 @@ fn pthread_rwlock_destroy(&mut self, rwlock_op: &OpTy<'tcx, Tag>) -> InterpResul
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_condattr_init(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// The default value of the clock attribute shall refer to the system
|
||||
@ -685,8 +721,8 @@ fn pthread_condattr_init(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResult<'
|
||||
|
||||
fn pthread_condattr_setclock(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
clock_id_op: &OpTy<'tcx, Tag>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
clock_id_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -705,8 +741,8 @@ fn pthread_condattr_setclock(
|
||||
|
||||
fn pthread_condattr_getclock(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
clk_id_op: &OpTy<'tcx, Tag>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
clk_id_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -716,7 +752,10 @@ fn pthread_condattr_getclock(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_condattr_destroy(
|
||||
&mut self,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
// Destroying an uninit pthread_condattr is UB, so check to make sure it's not uninit.
|
||||
@ -730,8 +769,8 @@ fn pthread_condattr_destroy(&mut self, attr_op: &OpTy<'tcx, Tag>) -> InterpResul
|
||||
|
||||
fn pthread_cond_init(
|
||||
&mut self,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
attr_op: &OpTy<'tcx, Tag>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
attr_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -750,7 +789,7 @@ fn pthread_cond_init(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = cond_get_or_create_id(this, cond_op)?;
|
||||
if let Some((thread, mutex)) = this.condvar_signal(id) {
|
||||
@ -760,7 +799,10 @@ fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Tag>) -> InterpResult<'tc
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_cond_broadcast(
|
||||
&mut self,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = cond_get_or_create_id(this, cond_op)?;
|
||||
|
||||
@ -773,8 +815,8 @@ fn pthread_cond_broadcast(&mut self, cond_op: &OpTy<'tcx, Tag>) -> InterpResult<
|
||||
|
||||
fn pthread_cond_wait(
|
||||
&mut self,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -790,10 +832,10 @@ fn pthread_cond_wait(
|
||||
|
||||
fn pthread_cond_timedwait(
|
||||
&mut self,
|
||||
cond_op: &OpTy<'tcx, Tag>,
|
||||
mutex_op: &OpTy<'tcx, Tag>,
|
||||
abstime_op: &OpTy<'tcx, Tag>,
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
mutex_op: &OpTy<'tcx, Provenance>,
|
||||
abstime_op: &OpTy<'tcx, Provenance>,
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -852,7 +894,10 @@ fn pthread_cond_timedwait(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn pthread_cond_destroy(&mut self, cond_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_cond_destroy(
|
||||
&mut self,
|
||||
cond_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let id = cond_get_or_create_id(this, cond_op)?;
|
||||
|
@ -6,10 +6,10 @@ impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tc
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn pthread_create(
|
||||
&mut self,
|
||||
thread: &OpTy<'tcx, Tag>,
|
||||
_attr: &OpTy<'tcx, Tag>,
|
||||
start_routine: &OpTy<'tcx, Tag>,
|
||||
arg: &OpTy<'tcx, Tag>,
|
||||
thread: &OpTy<'tcx, Provenance>,
|
||||
_attr: &OpTy<'tcx, Provenance>,
|
||||
start_routine: &OpTy<'tcx, Provenance>,
|
||||
arg: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -59,8 +59,8 @@ fn pthread_create(
|
||||
|
||||
fn pthread_join(
|
||||
&mut self,
|
||||
thread: &OpTy<'tcx, Tag>,
|
||||
retval: &OpTy<'tcx, Tag>,
|
||||
thread: &OpTy<'tcx, Provenance>,
|
||||
retval: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
@ -75,7 +75,7 @@ fn pthread_join(
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_detach(&mut self, thread: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
|
||||
fn pthread_detach(&mut self, thread: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let thread_id = this.read_scalar(thread)?.to_machine_usize(this)?;
|
||||
@ -84,14 +84,14 @@ fn pthread_detach(&mut self, thread: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_self(&mut self, dest: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn pthread_self(&mut self, dest: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
let thread_id = this.get_active_thread();
|
||||
this.write_scalar(Scalar::from_uint(thread_id.to_u32(), dest.layout.size), dest)
|
||||
}
|
||||
|
||||
fn prctl(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
|
||||
fn prctl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("linux", "prctl");
|
||||
|
||||
@ -138,7 +138,7 @@ fn prctl(&mut self, args: &[OpTy<'tcx, Tag>]) -> InterpResult<'tcx, i32> {
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
fn pthread_setname_np(&mut self, name: Pointer<Option<Tag>>) -> InterpResult<'tcx> {
|
||||
fn pthread_setname_np(&mut self, name: Pointer<Option<Provenance>>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
this.assert_target_os("macos", "pthread_setname_np");
|
||||
|
||||
|
@ -31,8 +31,8 @@ fn call_dlsym(
|
||||
&mut self,
|
||||
dlsym: Dlsym,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
ret: Option<mir::BasicBlock>,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
@ -15,8 +15,8 @@ fn emulate_foreign_item_by_name(
|
||||
&mut self,
|
||||
link_name: Symbol,
|
||||
abi: Abi,
|
||||
args: &[OpTy<'tcx, Tag>],
|
||||
dest: &PlaceTy<'tcx, Tag>,
|
||||
args: &[OpTy<'tcx, Provenance>],
|
||||
dest: &PlaceTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
fn srwlock_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
ecx: &mut MiriEvalContext<'mir, 'tcx>,
|
||||
lock_op: &OpTy<'tcx, Tag>,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, RwLockId> {
|
||||
let value_place = ecx.deref_operand_and_offset(lock_op, 0, ecx.machine.layouts.u32)?;
|
||||
|
||||
@ -34,7 +34,7 @@ fn srwlock_get_or_create_id<'mir, 'tcx: 'mir>(
|
||||
impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
#[allow(non_snake_case)]
|
||||
fn AcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn AcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = srwlock_get_or_create_id(this, lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
@ -56,7 +56,10 @@ fn AcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn TryAcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, u8> {
|
||||
fn TryAcquireSRWLockExclusive(
|
||||
&mut self,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, u8> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = srwlock_get_or_create_id(this, lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
@ -71,7 +74,7 @@ fn TryAcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpRes
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn ReleaseSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn ReleaseSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = srwlock_get_or_create_id(this, lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
@ -87,7 +90,7 @@ fn ReleaseSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn AcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn AcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = srwlock_get_or_create_id(this, lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
@ -102,7 +105,10 @@ fn AcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'t
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn TryAcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx, u8> {
|
||||
fn TryAcquireSRWLockShared(
|
||||
&mut self,
|
||||
lock_op: &OpTy<'tcx, Provenance>,
|
||||
) -> InterpResult<'tcx, u8> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = srwlock_get_or_create_id(this, lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
@ -116,7 +122,7 @@ fn TryAcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn ReleaseSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn ReleaseSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let id = srwlock_get_or_create_id(this, lock_op)?;
|
||||
let active_thread = this.get_active_thread();
|
||||
|
@ -5,11 +5,8 @@
|
||||
use rustc_target::abi::Size;
|
||||
|
||||
use crate::helpers::CurrentSpan;
|
||||
use crate::stacked_borrows::{err_sb_ub, AccessKind, Permission};
|
||||
use crate::Item;
|
||||
use crate::SbTag;
|
||||
use crate::SbTagExtra;
|
||||
use crate::Stack;
|
||||
use crate::stacked_borrows::{err_sb_ub, AccessKind};
|
||||
use crate::*;
|
||||
|
||||
use rustc_middle::mir::interpret::InterpError;
|
||||
|
||||
@ -132,7 +129,7 @@ pub fn get_logs_relevant_to(
|
||||
/// Report a descriptive error when `new` could not be granted from `derived_from`.
|
||||
pub fn grant_error<'tcx>(
|
||||
&self,
|
||||
derived_from: SbTagExtra,
|
||||
derived_from: ProvenanceExtra,
|
||||
new: Item,
|
||||
alloc_id: AllocId,
|
||||
alloc_range: AllocRange,
|
||||
@ -155,7 +152,7 @@ pub fn grant_error<'tcx>(
|
||||
pub fn access_error<'tcx>(
|
||||
&self,
|
||||
access: AccessKind,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
alloc_id: AllocId,
|
||||
alloc_range: AllocRange,
|
||||
error_offset: Size,
|
||||
@ -181,8 +178,8 @@ fn operation_summary(
|
||||
format!("this error occurs as part of {operation} at {alloc_id:?}{alloc_range:?}")
|
||||
}
|
||||
|
||||
fn error_cause(stack: &Stack, tag: SbTagExtra) -> &'static str {
|
||||
if let SbTagExtra::Concrete(tag) = tag {
|
||||
fn error_cause(stack: &Stack, prov_extra: ProvenanceExtra) -> &'static str {
|
||||
if let ProvenanceExtra::Concrete(tag) = prov_extra {
|
||||
if (0..stack.len())
|
||||
.map(|i| stack.get(i).unwrap())
|
||||
.any(|item| item.tag() == tag && item.perm() != Permission::Disabled)
|
||||
|
@ -55,32 +55,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
/// The "extra" information an SB pointer has over a regular AllocId.
|
||||
/// Newtype for `Option<SbTag>`.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum SbTagExtra {
|
||||
Concrete(SbTag),
|
||||
Wildcard,
|
||||
}
|
||||
|
||||
impl fmt::Debug for SbTagExtra {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
SbTagExtra::Concrete(pid) => write!(f, "{pid:?}"),
|
||||
SbTagExtra::Wildcard => write!(f, "<wildcard>"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SbTagExtra {
|
||||
fn and_then<T>(self, f: impl FnOnce(SbTag) -> Option<T>) -> Option<T> {
|
||||
match self {
|
||||
SbTagExtra::Concrete(pid) => f(pid),
|
||||
SbTagExtra::Wildcard => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FrameExtra {
|
||||
/// The ID of the call this frame corresponds to.
|
||||
@ -311,7 +285,7 @@ fn find_first_write_incompatible(&self, granting: usize) -> usize {
|
||||
/// currently checking.
|
||||
fn item_popped(
|
||||
item: &Item,
|
||||
provoking_access: Option<(SbTagExtra, AllocRange, Size, AccessKind)>, // just for debug printing and error messages
|
||||
provoking_access: Option<(ProvenanceExtra, AllocRange, Size, AccessKind)>, // just for debug printing and error messages
|
||||
global: &GlobalStateInner,
|
||||
alloc_history: &mut AllocHistory,
|
||||
threads: &ThreadManager<'_, 'tcx>,
|
||||
@ -322,7 +296,7 @@ fn item_popped(
|
||||
#[inline(never)] // cold path
|
||||
fn check_tracked(
|
||||
item: &Item,
|
||||
provoking_access: &Option<(SbTagExtra, AllocRange, Size, AccessKind)>,
|
||||
provoking_access: &Option<(ProvenanceExtra, AllocRange, Size, AccessKind)>,
|
||||
global: &GlobalStateInner,
|
||||
) {
|
||||
if global.tracked_pointer_tags.contains(&item.tag()) {
|
||||
@ -357,7 +331,7 @@ fn check_tracked(
|
||||
#[inline(never)] // cold path
|
||||
fn protector_error<'tcx>(
|
||||
item: &Item,
|
||||
provoking_access: &Option<(SbTagExtra, AllocRange, Size, AccessKind)>,
|
||||
provoking_access: &Option<(ProvenanceExtra, AllocRange, Size, AccessKind)>,
|
||||
alloc_history: &mut AllocHistory,
|
||||
threads: &ThreadManager<'_, 'tcx>,
|
||||
) -> InterpErrorInfo<'tcx> {
|
||||
@ -410,7 +384,7 @@ fn protector_error<'tcx>(
|
||||
fn access(
|
||||
&mut self,
|
||||
access: AccessKind,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
(alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
|
||||
global: &mut GlobalStateInner,
|
||||
current_span: &mut CurrentSpan<'_, '_, 'tcx>,
|
||||
@ -482,7 +456,7 @@ fn access(
|
||||
}
|
||||
|
||||
// If this was an approximate action, we now collapse everything into an unknown.
|
||||
if granting_idx.is_none() || matches!(tag, SbTagExtra::Wildcard) {
|
||||
if granting_idx.is_none() || matches!(tag, ProvenanceExtra::Wildcard) {
|
||||
// Compute the upper bound of the items that remain.
|
||||
// (This is why we did all the work above: to reduce the items we have to consider here.)
|
||||
let mut max = NonZeroU64::new(1).unwrap();
|
||||
@ -512,7 +486,7 @@ fn access(
|
||||
/// active protectors at all because we will remove all items.
|
||||
fn dealloc(
|
||||
&mut self,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
(alloc_id, _alloc_range, _offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
|
||||
global: &GlobalStateInner,
|
||||
alloc_history: &mut AllocHistory,
|
||||
@ -546,7 +520,7 @@ fn dealloc(
|
||||
/// `range` that we are currently checking.
|
||||
fn grant(
|
||||
&mut self,
|
||||
derived_from: SbTagExtra,
|
||||
derived_from: ProvenanceExtra,
|
||||
new: Item,
|
||||
(alloc_id, alloc_range, offset): (AllocId, AllocRange, Size), // just for debug printing and error messages
|
||||
global: &mut GlobalStateInner,
|
||||
@ -575,7 +549,7 @@ fn grant(
|
||||
"this case only makes sense for stack-like accesses"
|
||||
);
|
||||
|
||||
let (Some(granting_idx), SbTagExtra::Concrete(_)) = (granting_idx, derived_from) else {
|
||||
let (Some(granting_idx), ProvenanceExtra::Concrete(_)) = (granting_idx, derived_from) else {
|
||||
// The parent is a wildcard pointer or matched the unknown bottom.
|
||||
// This is approximate. Nobody knows what happened, so forget everything.
|
||||
// The new thing is SRW anyway, so we cannot push it "on top of the unkown part"
|
||||
@ -686,7 +660,7 @@ pub fn new_allocation(
|
||||
pub fn memory_read<'tcx>(
|
||||
&mut self,
|
||||
alloc_id: AllocId,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
range: AllocRange,
|
||||
state: &GlobalState,
|
||||
mut current_span: CurrentSpan<'_, '_, 'tcx>,
|
||||
@ -717,7 +691,7 @@ pub fn memory_read<'tcx>(
|
||||
pub fn memory_written<'tcx>(
|
||||
&mut self,
|
||||
alloc_id: AllocId,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
range: AllocRange,
|
||||
state: &GlobalState,
|
||||
mut current_span: CurrentSpan<'_, '_, 'tcx>,
|
||||
@ -748,7 +722,7 @@ pub fn memory_written<'tcx>(
|
||||
pub fn memory_deallocated<'tcx>(
|
||||
&mut self,
|
||||
alloc_id: AllocId,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
range: AllocRange,
|
||||
state: &GlobalState,
|
||||
threads: &ThreadManager<'_, 'tcx>,
|
||||
@ -770,7 +744,7 @@ trait EvalContextPrivExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
/// happened.
|
||||
fn reborrow(
|
||||
&mut self,
|
||||
place: &MPlaceTy<'tcx, Tag>,
|
||||
place: &MPlaceTy<'tcx, Provenance>,
|
||||
size: Size,
|
||||
kind: RefKind,
|
||||
new_tag: SbTag,
|
||||
@ -782,7 +756,7 @@ fn reborrow(
|
||||
// It is crucial that this gets called on all code paths, to ensure we track tag creation.
|
||||
let log_creation = |this: &MiriEvalContext<'mir, 'tcx>,
|
||||
current_span: &mut CurrentSpan<'_, 'mir, 'tcx>,
|
||||
loc: Option<(AllocId, Size, SbTagExtra)>| // alloc_id, base_offset, orig_tag
|
||||
loc: Option<(AllocId, Size, ProvenanceExtra)>| // alloc_id, base_offset, orig_tag
|
||||
-> InterpResult<'tcx> {
|
||||
let global = this.machine.stacked_borrows.as_ref().unwrap().borrow();
|
||||
if global.tracked_pointer_tags.contains(&new_tag) {
|
||||
@ -798,7 +772,7 @@ fn reborrow(
|
||||
};
|
||||
|
||||
// The SB history tracking needs a parent tag, so skip if we come from a wildcard.
|
||||
let SbTagExtra::Concrete(orig_tag) = orig_tag else {
|
||||
let ProvenanceExtra::Concrete(orig_tag) = orig_tag else {
|
||||
// FIXME: should we log this?
|
||||
return Ok(())
|
||||
};
|
||||
@ -972,10 +946,10 @@ fn reborrow(
|
||||
/// `mutbl` can be `None` to make this a raw pointer.
|
||||
fn retag_reference(
|
||||
&mut self,
|
||||
val: &ImmTy<'tcx, Tag>,
|
||||
val: &ImmTy<'tcx, Provenance>,
|
||||
kind: RefKind,
|
||||
protect: bool,
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Tag>> {
|
||||
) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
// We want a place for where the ptr *points to*, so we get one.
|
||||
let place = this.ref_to_mplace(val)?;
|
||||
@ -1001,12 +975,12 @@ fn retag_reference(
|
||||
Some(alloc_id) => {
|
||||
// If `reborrow` could figure out the AllocId of this ptr, hard-code it into the new one.
|
||||
// Even if we started out with a wildcard, this newly retagged pointer is tied to that allocation.
|
||||
Tag::Concrete { alloc_id, sb: new_tag }
|
||||
Provenance::Concrete { alloc_id, sb: new_tag }
|
||||
}
|
||||
None => {
|
||||
// Looks like this has to stay a wildcard pointer.
|
||||
assert!(matches!(prov, Tag::Wildcard));
|
||||
Tag::Wildcard
|
||||
assert!(matches!(prov, Provenance::Wildcard));
|
||||
Provenance::Wildcard
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -1019,7 +993,7 @@ fn retag_reference(
|
||||
|
||||
impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
|
||||
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
|
||||
fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn retag(&mut self, kind: RetagKind, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
let retag_fields = this.machine.stacked_borrows.as_mut().unwrap().get_mut().retag_fields;
|
||||
let mut visitor = RetagVisitor { ecx: this, kind, retag_fields };
|
||||
@ -1057,7 +1031,7 @@ impl<'ecx, 'mir, 'tcx> RetagVisitor<'ecx, 'mir, 'tcx> {
|
||||
#[inline(always)] // yes this helps in our benchmarks
|
||||
fn retag_place(
|
||||
&mut self,
|
||||
place: &PlaceTy<'tcx, Tag>,
|
||||
place: &PlaceTy<'tcx, Provenance>,
|
||||
ref_kind: RefKind,
|
||||
protector: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
@ -1070,14 +1044,14 @@ fn retag_place(
|
||||
impl<'ecx, 'mir, 'tcx> MutValueVisitor<'mir, 'tcx, Evaluator<'mir, 'tcx>>
|
||||
for RetagVisitor<'ecx, 'mir, 'tcx>
|
||||
{
|
||||
type V = PlaceTy<'tcx, Tag>;
|
||||
type V = PlaceTy<'tcx, Provenance>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&mut self) -> &mut MiriEvalContext<'mir, 'tcx> {
|
||||
self.ecx
|
||||
}
|
||||
|
||||
fn visit_box(&mut self, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn visit_box(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
// Boxes do not get a protector: protectors reflect that references outlive the call
|
||||
// they were passed in to; that's just not the case for boxes.
|
||||
self.retag_place(
|
||||
@ -1087,7 +1061,7 @@ fn visit_box(&mut self, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_value(&mut self, place: &PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
|
||||
fn visit_value(&mut self, place: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
|
||||
if let Some((ref_kind, protector)) = qualify(place.layout.ty, self.kind) {
|
||||
self.retag_place(place, ref_kind, protector)?;
|
||||
} else if matches!(place.layout.ty.kind(), ty::RawPtr(..)) {
|
||||
|
@ -1,8 +1,11 @@
|
||||
use crate::stacked_borrows::{AccessKind, Item, Permission, SbTag, SbTagExtra};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
#[cfg(feature = "stack-cache")]
|
||||
use std::ops::Range;
|
||||
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
||||
use crate::stacked_borrows::{AccessKind, Item, Permission, SbTag};
|
||||
use crate::ProvenanceExtra;
|
||||
|
||||
/// Exactly what cache size we should use is a difficult tradeoff. There will always be some
|
||||
/// workload which has a `SbTag` working set which exceeds the size of the cache, and ends up
|
||||
/// falling back to linear searches of the borrow stack very often.
|
||||
@ -126,13 +129,13 @@ fn verify_cache_consistency(&self) {
|
||||
pub(super) fn find_granting(
|
||||
&mut self,
|
||||
access: AccessKind,
|
||||
tag: SbTagExtra,
|
||||
tag: ProvenanceExtra,
|
||||
exposed_tags: &FxHashSet<SbTag>,
|
||||
) -> Result<Option<usize>, ()> {
|
||||
#[cfg(debug_assertions)]
|
||||
self.verify_cache_consistency();
|
||||
|
||||
let SbTagExtra::Concrete(tag) = tag else {
|
||||
let ProvenanceExtra::Concrete(tag) = tag else {
|
||||
// Handle the wildcard case.
|
||||
// Go search the stack for an exposed tag.
|
||||
if let Some(idx) =
|
||||
|
@ -42,7 +42,7 @@ fn index(self) -> usize {
|
||||
}
|
||||
|
||||
impl $name {
|
||||
pub fn to_u32_scalar<'tcx>(&self) -> Scalar<Tag> {
|
||||
pub fn to_u32_scalar<'tcx>(&self) -> Scalar<Provenance> {
|
||||
Scalar::from_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ fn from(id: u32) -> Self {
|
||||
}
|
||||
|
||||
impl ThreadId {
|
||||
pub fn to_u32_scalar(&self) -> Scalar<Tag> {
|
||||
pub fn to_u32_scalar(&self) -> Scalar<Provenance> {
|
||||
Scalar::from_u32(self.0)
|
||||
}
|
||||
}
|
||||
@ -112,7 +112,7 @@ pub struct Thread<'mir, 'tcx> {
|
||||
thread_name: Option<Vec<u8>>,
|
||||
|
||||
/// The virtual call stack.
|
||||
stack: Vec<Frame<'mir, 'tcx, Tag, FrameData<'tcx>>>,
|
||||
stack: Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>>,
|
||||
|
||||
/// The join status.
|
||||
join_status: ThreadJoinStatus,
|
||||
@ -120,10 +120,10 @@ pub struct Thread<'mir, 'tcx> {
|
||||
/// The temporary used for storing the argument of
|
||||
/// the call to `miri_start_panic` (the panic payload) when unwinding.
|
||||
/// This is pointer-sized, and matches the `Payload` type in `src/libpanic_unwind/miri.rs`.
|
||||
pub(crate) panic_payload: Option<Scalar<Tag>>,
|
||||
pub(crate) panic_payload: Option<Scalar<Provenance>>,
|
||||
|
||||
/// Last OS error location in memory. It is a 32-bit integer.
|
||||
pub(crate) last_error: Option<MPlaceTy<'tcx, Tag>>,
|
||||
pub(crate) last_error: Option<MPlaceTy<'tcx, Provenance>>,
|
||||
}
|
||||
|
||||
impl<'mir, 'tcx> Thread<'mir, 'tcx> {
|
||||
@ -227,7 +227,7 @@ pub struct ThreadManager<'mir, 'tcx> {
|
||||
pub(crate) sync: SynchronizationState,
|
||||
/// A mapping from a thread-local static to an allocation id of a thread
|
||||
/// specific allocation.
|
||||
thread_local_alloc_ids: RefCell<FxHashMap<(DefId, ThreadId), Pointer<Tag>>>,
|
||||
thread_local_alloc_ids: RefCell<FxHashMap<(DefId, ThreadId), Pointer<Provenance>>>,
|
||||
/// A flag that indicates that we should change the active thread.
|
||||
yield_active_thread: bool,
|
||||
/// Callbacks that are called once the specified time passes.
|
||||
@ -256,7 +256,7 @@ fn default() -> Self {
|
||||
impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
|
||||
/// Check if we have an allocation for the given thread local static for the
|
||||
/// active thread.
|
||||
fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Tag>> {
|
||||
fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Provenance>> {
|
||||
self.thread_local_alloc_ids.borrow().get(&(def_id, self.active_thread)).cloned()
|
||||
}
|
||||
|
||||
@ -264,7 +264,7 @@ fn get_thread_local_alloc_id(&self, def_id: DefId) -> Option<Pointer<Tag>> {
|
||||
/// static for the active thread.
|
||||
///
|
||||
/// Panics if a thread local is initialized twice for the same thread.
|
||||
fn set_thread_local_alloc(&self, def_id: DefId, ptr: Pointer<Tag>) {
|
||||
fn set_thread_local_alloc(&self, def_id: DefId, ptr: Pointer<Provenance>) {
|
||||
self.thread_local_alloc_ids
|
||||
.borrow_mut()
|
||||
.try_insert((def_id, self.active_thread), ptr)
|
||||
@ -272,16 +272,20 @@ fn set_thread_local_alloc(&self, def_id: DefId, ptr: Pointer<Tag>) {
|
||||
}
|
||||
|
||||
/// Borrow the stack of the active thread.
|
||||
pub fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Tag, FrameData<'tcx>>] {
|
||||
pub fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>] {
|
||||
&self.threads[self.active_thread].stack
|
||||
}
|
||||
|
||||
/// Mutably borrow the stack of the active thread.
|
||||
fn active_thread_stack_mut(&mut self) -> &mut Vec<Frame<'mir, 'tcx, Tag, FrameData<'tcx>>> {
|
||||
fn active_thread_stack_mut(
|
||||
&mut self,
|
||||
) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>> {
|
||||
&mut self.threads[self.active_thread].stack
|
||||
}
|
||||
|
||||
pub fn all_stacks(&self) -> impl Iterator<Item = &[Frame<'mir, 'tcx, Tag, FrameData<'tcx>>]> {
|
||||
pub fn all_stacks(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &[Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>]> {
|
||||
self.threads.iter().map(|t| &t.stack[..])
|
||||
}
|
||||
|
||||
@ -468,7 +472,7 @@ fn get_ready_callback(&mut self) -> Option<(ThreadId, TimeoutCallback<'mir, 'tcx
|
||||
fn thread_terminated(
|
||||
&mut self,
|
||||
mut data_race: Option<&mut data_race::GlobalState>,
|
||||
) -> Vec<Pointer<Tag>> {
|
||||
) -> Vec<Pointer<Provenance>> {
|
||||
let mut free_tls_statics = Vec::new();
|
||||
{
|
||||
let mut thread_local_statics = self.thread_local_alloc_ids.borrow_mut();
|
||||
@ -589,7 +593,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
|
||||
fn get_or_create_thread_local_alloc(
|
||||
&mut self,
|
||||
def_id: DefId,
|
||||
) -> InterpResult<'tcx, Pointer<Tag>> {
|
||||
) -> InterpResult<'tcx, Pointer<Provenance>> {
|
||||
let this = self.eval_context_mut();
|
||||
let tcx = this.tcx;
|
||||
if let Some(old_alloc) = this.machine.threads.get_thread_local_alloc_id(def_id) {
|
||||
@ -686,13 +690,15 @@ fn enable_thread(&mut self, thread_id: ThreadId) {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Tag, FrameData<'tcx>>] {
|
||||
fn active_thread_stack(&self) -> &[Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>] {
|
||||
let this = self.eval_context_ref();
|
||||
this.machine.threads.active_thread_stack()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn active_thread_stack_mut(&mut self) -> &mut Vec<Frame<'mir, 'tcx, Tag, FrameData<'tcx>>> {
|
||||
fn active_thread_stack_mut(
|
||||
&mut self,
|
||||
) -> &mut Vec<Frame<'mir, 'tcx, Provenance, FrameData<'tcx>>> {
|
||||
let this = self.eval_context_mut();
|
||||
this.machine.threads.active_thread_stack_mut()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user