diff --git a/src/concurrency/init_once.rs b/src/concurrency/init_once.rs index eb42cdf80a..77fdd14ffa 100644 --- a/src/concurrency/init_once.rs +++ b/src/concurrency/init_once.rs @@ -2,6 +2,7 @@ use std::collections::VecDeque; use std::num::NonZeroU32; use rustc_index::vec::Idx; +use rustc_middle::ty::layout::TyAndLayout; use super::sync::EvalContextExtPriv as _; use super::thread::MachineCallback; @@ -94,10 +95,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn init_once_get_or_create_id( &mut self, lock_op: &OpTy<'tcx, Provenance>, + lock_layout: TyAndLayout<'tcx>, offset: u64, ) -> InterpResult<'tcx, InitOnceId> { let this = self.eval_context_mut(); - this.init_once_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset)) + this.init_once_get_or_create(|ecx, next_id| { + ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) + }) } /// Provides the closure with the next InitOnceId. Creates that InitOnce if the closure returns None, diff --git a/src/concurrency/sync.rs b/src/concurrency/sync.rs index dc4b435b71..81f4506859 100644 --- a/src/concurrency/sync.rs +++ b/src/concurrency/sync.rs @@ -6,6 +6,7 @@ use log::trace; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::ty::layout::TyAndLayout; use super::init_once::InitOnce; use super::vector_clock::VClock; @@ -200,11 +201,12 @@ pub(super) trait EvalContextExtPriv<'mir, 'tcx: 'mir>: &mut self, next_id: Id, lock_op: &OpTy<'tcx, Provenance>, + lock_layout: TyAndLayout<'tcx>, offset: u64, ) -> InterpResult<'tcx, Option> { let this = self.eval_context_mut(); let value_place = - this.deref_operand_and_offset(lock_op, offset, this.machine.layouts.u32)?; + this.deref_operand_and_offset(lock_op, offset, lock_layout, this.machine.layouts.u32)?; // Since we are lazy, this update has to be atomic. let (old, success) = this @@ -278,28 +280,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn mutex_get_or_create_id( &mut self, lock_op: &OpTy<'tcx, Provenance>, + lock_layout: TyAndLayout<'tcx>, offset: u64, ) -> InterpResult<'tcx, MutexId> { let this = self.eval_context_mut(); - this.mutex_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset)) + this.mutex_get_or_create(|ecx, next_id| { + ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) + }) } fn rwlock_get_or_create_id( &mut self, lock_op: &OpTy<'tcx, Provenance>, + lock_layout: TyAndLayout<'tcx>, offset: u64, ) -> InterpResult<'tcx, RwLockId> { let this = self.eval_context_mut(); - this.rwlock_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset)) + this.rwlock_get_or_create(|ecx, next_id| { + ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) + }) } fn condvar_get_or_create_id( &mut self, lock_op: &OpTy<'tcx, Provenance>, + lock_layout: TyAndLayout<'tcx>, offset: u64, ) -> InterpResult<'tcx, CondvarId> { let this = self.eval_context_mut(); - this.condvar_get_or_create(|ecx, next_id| ecx.get_or_create_id(next_id, lock_op, offset)) + this.condvar_get_or_create(|ecx, next_id| { + ecx.get_or_create_id(next_id, lock_op, lock_layout, offset) + }) } #[inline] diff --git a/src/helpers.rs b/src/helpers.rs index f66b2de504..ac06c82e87 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -664,20 +664,37 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } + /// Dereference a pointer operand to a place using `layout` instead of the pointer's declared type + fn deref_operand_as( + &self, + op: &OpTy<'tcx, Provenance>, + layout: TyAndLayout<'tcx>, + ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { + let this = self.eval_context_ref(); + let ptr = this.read_pointer(op)?; + + let mplace = MPlaceTy::from_aligned_ptr(ptr, layout); + + this.check_mplace(mplace)?; + + Ok(mplace) + } + /// Calculates the MPlaceTy given the offset and layout of an access on an operand fn deref_operand_and_offset( &self, op: &OpTy<'tcx, Provenance>, offset: u64, - layout: TyAndLayout<'tcx>, + base_layout: TyAndLayout<'tcx>, + value_layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, MPlaceTy<'tcx, Provenance>> { let this = self.eval_context_ref(); - let op_place = this.deref_operand(op)?; // FIXME: we still deref with the original type! + let op_place = this.deref_operand_as(op, base_layout)?; let offset = Size::from_bytes(offset); // Ensure that the access is within bounds. - assert!(op_place.layout.size >= offset + layout.size); - let value_place = op_place.offset(offset, layout, this)?; + assert!(base_layout.size >= offset + value_layout.size); + let value_place = op_place.offset(offset, value_layout, this)?; Ok(value_place) } @@ -685,10 +702,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &self, op: &OpTy<'tcx, Provenance>, offset: u64, - layout: TyAndLayout<'tcx>, + base_layout: TyAndLayout<'tcx>, + value_layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_ref(); - let value_place = this.deref_operand_and_offset(op, offset, layout)?; + let value_place = this.deref_operand_and_offset(op, offset, base_layout, value_layout)?; this.read_scalar(&value_place.into()) } @@ -697,10 +715,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { op: &OpTy<'tcx, Provenance>, offset: u64, value: impl Into>, - layout: TyAndLayout<'tcx>, + base_layout: TyAndLayout<'tcx>, + value_layout: TyAndLayout<'tcx>, ) -> InterpResult<'tcx, ()> { let this = self.eval_context_mut(); - let value_place = this.deref_operand_and_offset(op, offset, layout)?; + let value_place = this.deref_operand_and_offset(op, offset, base_layout, value_layout)?; this.write_scalar(value, &value_place.into()) } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index 058f730833..53d05921b7 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -403,7 +403,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // // First thing: load all the arguments. Details depend on the shim. // let arg1 = this.read_scalar(arg1)?.to_u32()?; // let arg2 = this.read_pointer(arg2)?; // when you need to work with the pointer directly - // let arg3 = this.deref_operand(arg3)?; // when you want to load/store through the pointer at its declared type + // let arg3 = this.deref_operand_as(arg3, this.machine.layouts.u64)?; // when you want to load/store through the pointer // // // ... // diff --git a/src/shims/time.rs b/src/shims/time.rs index 617f90dfaa..88c735c54b 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -25,6 +25,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("linux", "clock_gettime"); let clk_id = this.read_scalar(clk_id_op)?.to_i32()?; + let tp = this.deref_operand_as(tp_op, this.libc_ty_layout("timespec")?)?; // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the // Unix epoch, including effects which may cause time to move backwards such as NTP. @@ -52,7 +53,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let tv_sec = duration.as_secs(); let tv_nsec = duration.subsec_nanos(); - this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &this.deref_operand(tp_op)?)?; + this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &tp)?; Ok(Scalar::from_i32(0)) } @@ -67,6 +68,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os_is_unix("gettimeofday"); this.check_no_isolation("`gettimeofday`")?; + let tv = this.deref_operand_as(tv_op, this.libc_ty_layout("timeval")?)?; + // Using tz is obsolete and should always be null let tz = this.read_pointer(tz_op)?; if !this.ptr_is_null(tz)? { @@ -79,7 +82,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let tv_sec = duration.as_secs(); let tv_usec = duration.subsec_micros(); - this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &this.deref_operand(tv_op)?)?; + this.write_int_fields(&[tv_sec.into(), tv_usec.into()], &tv)?; Ok(0) } @@ -94,6 +97,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("windows", "GetSystemTimeAsFileTime"); this.check_no_isolation("`GetSystemTimeAsFileTime`")?; + let filetime = this.deref_operand_as(LPFILETIME_op, this.windows_ty_layout("FILETIME")?)?; + let NANOS_PER_SEC = this.eval_windows_u64("time", "NANOS_PER_SEC")?; let INTERVALS_PER_SEC = this.eval_windows_u64("time", "INTERVALS_PER_SEC")?; let INTERVALS_TO_UNIX_EPOCH = this.eval_windows_u64("time", "INTERVALS_TO_UNIX_EPOCH")?; @@ -107,10 +112,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap(); let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap(); - this.write_int_fields( - &[dwLowDateTime.into(), dwHighDateTime.into()], - &this.deref_operand(LPFILETIME_op)?, - )?; + this.write_int_fields(&[dwLowDateTime.into(), dwHighDateTime.into()], &filetime)?; Ok(()) } @@ -132,7 +134,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { })?; this.write_scalar( Scalar::from_i64(qpc), - &this.deref_operand(lpPerformanceCount_op)?.into(), + &this.deref_operand_as(lpPerformanceCount_op, this.machine.layouts.u64)?.into(), )?; Ok(Scalar::from_i32(-1)) // return non-zero on success } @@ -153,7 +155,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // and thus 10^9 counts per second. this.write_scalar( Scalar::from_i64(1_000_000_000), - &this.deref_operand(lpFrequency_op)?.into(), + &this.deref_operand_as(lpFrequency_op, this.machine.layouts.u64)?.into(), )?; Ok(Scalar::from_i32(-1)) // Return non-zero on success } @@ -180,7 +182,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os("macos", "mach_timebase_info"); - let info = this.deref_operand(info_op)?; + let info = this.deref_operand_as(info_op, this.libc_ty_layout("mach_timebase_info")?)?; // Since our emulated ticks in `mach_absolute_time` *are* nanoseconds, // no scaling needs to happen. @@ -199,7 +201,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.assert_target_os_is_unix("nanosleep"); - let duration = match this.read_timespec(&this.deref_operand(req_op)?)? { + let req = this.deref_operand_as(req_op, this.libc_ty_layout("timespec")?)?; + + let duration = match this.read_timespec(&req)? { Some(duration) => duration, None => { let einval = this.eval_libc("EINVAL")?; diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs index 44a433df1e..3089964d60 100644 --- a/src/shims/unix/foreign_items.rs +++ b/src/shims/unix/foreign_items.rs @@ -184,7 +184,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Allocation "posix_memalign" => { let [ret, align, size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let ret = this.deref_operand(ret)?; + let ret = this.deref_operand_as(ret, this.machine.layouts.mut_raw_ptr)?; let align = this.read_scalar(align)?.to_machine_usize(this)?; let size = this.read_scalar(size)?.to_machine_usize(this)?; // Align must be power of 2, and also at least ptr-sized (POSIX rules). @@ -253,7 +253,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Thread-local storage "pthread_key_create" => { let [key, dtor] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let key_place = this.deref_operand(key)?; + let key_place = this.deref_operand_as(key, this.libc_ty_layout("pthread_key_t")?)?; let dtor = this.read_pointer(dtor)?; // Extract the function type out of the signature (that seems easier than constructing it ourselves). @@ -488,7 +488,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "pthread_attr_getguardsize" if this.frame_in_std() => { let [_attr, guard_size] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let guard_size = this.deref_operand(guard_size)?; + let guard_size = this.deref_operand_as(guard_size, this.machine.layouts.usize)?; let guard_size_layout = this.libc_ty_layout("size_t")?; this.write_scalar(Scalar::from_uint(crate::PAGE_SIZE, guard_size_layout.size), &guard_size.into())?; @@ -514,9 +514,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Hence we can mostly ignore the input `attr_place`. let [attr_place, addr_place, size_place] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let _attr_place = this.deref_operand(attr_place)?; - let addr_place = this.deref_operand(addr_place)?; - let size_place = this.deref_operand(size_place)?; + let _attr_place = this.deref_operand_as(attr_place, this.libc_ty_layout("pthread_attr_t")?)?; + let addr_place = this.deref_operand_as(addr_place, this.machine.layouts.mut_raw_ptr)?; + let size_place = this.deref_operand_as(size_place, this.machine.layouts.usize)?; this.write_scalar( Scalar::from_uint(STACK_ADDR, this.pointer_size()), @@ -557,10 +557,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_no_isolation("`getpwuid_r`")?; let uid = this.read_scalar(uid)?.to_u32()?; - let pwd = this.deref_operand(pwd)?; + let pwd = this.deref_operand_as(pwd, this.libc_ty_layout("passwd")?)?; let buf = this.read_pointer(buf)?; let buflen = this.read_scalar(buflen)?.to_machine_usize(this)?; - let result = this.deref_operand(result)?; + let result = this.deref_operand_as(result, this.machine.layouts.mut_raw_ptr)?; // Must be for "us". if uid != crate::shims::unix::UID { diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs index b152082b4d..9932043161 100644 --- a/src/shims/unix/fs.rs +++ b/src/shims/unix/fs.rs @@ -11,7 +11,6 @@ use std::time::SystemTime; use log::trace; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::{self, layout::LayoutOf}; use rustc_target::abi::{Align, Size}; use crate::shims::os_str::bytes_to_os_str; @@ -347,7 +346,8 @@ trait EvalContextExtPrivate<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx let (created_sec, created_nsec) = metadata.created.unwrap_or((0, 0)); let (modified_sec, modified_nsec) = metadata.modified.unwrap_or((0, 0)); - let buf = this.deref_operand(buf_op)?; + let buf = this.deref_operand_as(buf_op, this.libc_ty_layout("stat")?)?; + this.write_int_fields_named( &[ ("st_dev", 0), @@ -1000,20 +1000,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(-1); } - // Under normal circumstances, we would use `deref_operand(statxbuf_op)` to produce a - // proper `MemPlace` and then write the results of this function to it. However, the - // `syscall` function is untyped. This means that all the `statx` parameters are provided - // as `isize`s instead of having the proper types. Thus, we have to recover the layout of - // `statxbuf_op` by using the `libc::statx` struct type. - let statxbuf = { - // FIXME: This long path is required because `libc::statx` is an struct and also a - // function and `resolve_path` is returning the latter. - let statx_ty = this - .resolve_path(&["libc", "unix", "linux_like", "linux", "gnu", "statx"]) - .ty(*this.tcx, ty::ParamEnv::reveal_all()); - let statx_layout = this.layout_of(statx_ty)?; - MPlaceTy::from_aligned_ptr(statxbuf_ptr, statx_layout) - }; + let statxbuf = this.deref_operand_as(statxbuf_op, this.libc_ty_layout("statx")?)?; let path = this.read_path_from_c_str(pathname_ptr)?.into_owned(); // See for a discussion of argument sizes. @@ -1419,7 +1406,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // pub d_name: [c_char; 1024], // } - let entry_place = this.deref_operand(entry_op)?; + let entry_place = + this.deref_operand_as(entry_op, this.libc_ty_layout("dirent")?)?; let name_place = this.mplace_field(&entry_place, 5)?; let file_name = dir_entry.file_name(); // not a Path as there are no separators! @@ -1435,8 +1423,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ); } - let entry_place = this.deref_operand(entry_op)?; - // If the host is a Unix system, fill in the inode number with its real value. // If not, use 0 as a fallback value. #[cfg(unix)] @@ -1457,14 +1443,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { &entry_place, )?; - let result_place = this.deref_operand(result_op)?; + let result_place = + this.deref_operand_as(result_op, this.machine.layouts.mut_raw_ptr)?; this.write_scalar(this.read_scalar(entry_op)?, &result_place.into())?; 0 } None => { // end of stream: return 0, assign *result=NULL - this.write_null(&this.deref_operand(result_op)?.into())?; + this.write_null( + &this.deref_operand_as(result_op, this.machine.layouts.mut_raw_ptr)?.into(), + )?; 0 } Some(Err(e)) => diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs index 2b53152688..0ce4a17cef 100644 --- a/src/shims/unix/linux/foreign_items.rs +++ b/src/shims/unix/linux/foreign_items.rs @@ -157,7 +157,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; this.read_scalar(pid)?.to_i32()?; this.read_scalar(cpusetsize)?.to_machine_usize(this)?; - this.deref_operand(mask)?; + this.deref_operand_as(mask, this.libc_ty_layout("cpu_set_t")?)?; // FIXME: we just return an error; `num_cpus` then falls back to `sysconf`. let einval = this.eval_libc("EINVAL")?; this.set_last_error(einval)?; diff --git a/src/shims/unix/linux/sync.rs b/src/shims/unix/linux/sync.rs index 292b9d2e7a..8f6c79ba0f 100644 --- a/src/shims/unix/linux/sync.rs +++ b/src/shims/unix/linux/sync.rs @@ -85,9 +85,8 @@ pub fn futex<'tcx>( return Ok(()); } - // `deref_operand` but not actually dereferencing the ptr yet (it might be NULL!). - let timeout = this.ref_to_mplace(&this.read_immediate(&args[3])?)?; - let timeout_time = if this.ptr_is_null(timeout.ptr)? { + let timeout_op = &args[3]; + let timeout_time = if this.ptr_is_null(this.read_pointer(timeout_op)?)? { None } else { if op & futex_realtime != 0 { @@ -95,6 +94,8 @@ pub fn futex<'tcx>( "`futex` syscall with `op=FUTEX_WAIT` and non-null timeout with `FUTEX_CLOCK_REALTIME`", )?; } + let timeout = + this.deref_operand_as(timeout_op, this.libc_ty_layout("timespec")?)?; let duration = match this.read_timespec(&timeout)? { Some(duration) => duration, None => { diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs index 221dc39697..b72d4f435b 100644 --- a/src/shims/unix/macos/foreign_items.rs +++ b/src/shims/unix/macos/foreign_items.rs @@ -125,7 +125,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_no_isolation("`_NSGetExecutablePath`")?; let buf_ptr = this.read_pointer(buf)?; - let bufsize = this.deref_operand(bufsize)?; + let bufsize = this.deref_operand_as(bufsize, this.machine.layouts.u32)?; // Using the host current_exe is a bit off, but consistent with Linux // (where stdlib reads /proc/self/exe). diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs index e0afb500cb..9a547bc7f9 100644 --- a/src/shims/unix/sync.rs +++ b/src/shims/unix/sync.rs @@ -36,7 +36,13 @@ fn mutexattr_get_kind<'mir, 'tcx: 'mir>( ecx: &MiriInterpCx<'mir, 'tcx>, attr_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { - ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)?.to_i32() + ecx.read_scalar_at_offset( + attr_op, + 0, + ecx.libc_ty_layout("pthread_mutexattr_t")?, + ecx.machine.layouts.i32, + )? + .to_i32() } fn mutexattr_set_kind<'mir, 'tcx: 'mir>( @@ -44,7 +50,13 @@ fn mutexattr_set_kind<'mir, 'tcx: 'mir>( attr_op: &OpTy<'tcx, Provenance>, kind: i32, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset(attr_op, 0, Scalar::from_i32(kind), ecx.machine.layouts.i32) + ecx.write_scalar_at_offset( + attr_op, + 0, + Scalar::from_i32(kind), + ecx.libc_ty_layout("pthread_mutexattr_t")?, + ecx.machine.layouts.i32, + ) } // pthread_mutex_t is between 24 and 48 bytes, depending on the platform. @@ -60,14 +72,20 @@ fn mutex_get_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, mutex_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, MutexId> { - ecx.mutex_get_or_create_id(mutex_op, 4) + ecx.mutex_get_or_create_id(mutex_op, ecx.libc_ty_layout("pthread_mutex_t")?, 4) } fn mutex_reset_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, mutex_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset(mutex_op, 4, Scalar::from_i32(0), ecx.machine.layouts.u32) + ecx.write_scalar_at_offset( + mutex_op, + 4, + Scalar::from_i32(0), + ecx.libc_ty_layout("pthread_mutex_t")?, + ecx.machine.layouts.u32, + ) } fn mutex_get_kind<'mir, 'tcx: 'mir>( @@ -75,7 +93,13 @@ fn mutex_get_kind<'mir, 'tcx: 'mir>( mutex_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - ecx.read_scalar_at_offset(mutex_op, offset, ecx.machine.layouts.i32)?.to_i32() + ecx.read_scalar_at_offset( + mutex_op, + offset, + ecx.libc_ty_layout("pthread_mutex_t")?, + ecx.machine.layouts.i32, + )? + .to_i32() } fn mutex_set_kind<'mir, 'tcx: 'mir>( @@ -84,7 +108,13 @@ fn mutex_set_kind<'mir, 'tcx: 'mir>( kind: i32, ) -> InterpResult<'tcx, ()> { let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 }; - ecx.write_scalar_at_offset(mutex_op, offset, Scalar::from_i32(kind), ecx.machine.layouts.i32) + ecx.write_scalar_at_offset( + mutex_op, + offset, + Scalar::from_i32(kind), + ecx.libc_ty_layout("pthread_mutex_t")?, + ecx.machine.layouts.i32, + ) } // pthread_rwlock_t is between 32 and 56 bytes, depending on the platform. @@ -98,7 +128,7 @@ fn rwlock_get_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, rwlock_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, RwLockId> { - ecx.rwlock_get_or_create_id(rwlock_op, 4) + ecx.rwlock_get_or_create_id(rwlock_op, ecx.libc_ty_layout("pthread_rwlock_t")?, 4) } // pthread_condattr_t @@ -111,7 +141,13 @@ fn condattr_get_clock_id<'mir, 'tcx: 'mir>( ecx: &MiriInterpCx<'mir, 'tcx>, attr_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { - ecx.read_scalar_at_offset(attr_op, 0, ecx.machine.layouts.i32)?.to_i32() + ecx.read_scalar_at_offset( + attr_op, + 0, + ecx.libc_ty_layout("pthread_condattr_t")?, + ecx.machine.layouts.i32, + )? + .to_i32() } fn condattr_set_clock_id<'mir, 'tcx: 'mir>( @@ -119,7 +155,13 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>( attr_op: &OpTy<'tcx, Provenance>, clock_id: i32, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset(attr_op, 0, Scalar::from_i32(clock_id), ecx.machine.layouts.i32) + ecx.write_scalar_at_offset( + attr_op, + 0, + Scalar::from_i32(clock_id), + ecx.libc_ty_layout("pthread_condattr_t")?, + ecx.machine.layouts.i32, + ) } // pthread_cond_t @@ -135,21 +177,33 @@ fn cond_get_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, cond_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, CondvarId> { - ecx.condvar_get_or_create_id(cond_op, 4) + ecx.condvar_get_or_create_id(cond_op, ecx.libc_ty_layout("pthread_cond_t")?, 4) } fn cond_reset_id<'mir, 'tcx: 'mir>( ecx: &mut MiriInterpCx<'mir, 'tcx>, cond_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset(cond_op, 4, Scalar::from_i32(0), ecx.machine.layouts.u32) + ecx.write_scalar_at_offset( + cond_op, + 4, + Scalar::from_i32(0), + ecx.libc_ty_layout("pthread_cond_t")?, + ecx.machine.layouts.u32, + ) } fn cond_get_clock_id<'mir, 'tcx: 'mir>( ecx: &MiriInterpCx<'mir, 'tcx>, cond_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, i32> { - ecx.read_scalar_at_offset(cond_op, 8, ecx.machine.layouts.i32)?.to_i32() + ecx.read_scalar_at_offset( + cond_op, + 8, + ecx.libc_ty_layout("pthread_cond_t")?, + ecx.machine.layouts.i32, + )? + .to_i32() } fn cond_set_clock_id<'mir, 'tcx: 'mir>( @@ -157,7 +211,13 @@ fn cond_set_clock_id<'mir, 'tcx: 'mir>( cond_op: &OpTy<'tcx, Provenance>, clock_id: i32, ) -> InterpResult<'tcx, ()> { - ecx.write_scalar_at_offset(cond_op, 8, Scalar::from_i32(clock_id), ecx.machine.layouts.i32) + ecx.write_scalar_at_offset( + cond_op, + 8, + Scalar::from_i32(clock_id), + ecx.libc_ty_layout("pthread_cond_t")?, + ecx.machine.layouts.i32, + ) } /// Try to reacquire the mutex associated with the condition variable after we @@ -285,7 +345,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // However, the way libstd uses the pthread APIs works in our favor here, so we can get away with this. // This can always be revisited to have some external state to catch double-destroys // but not complain about the above code. See /~https://github.com/rust-lang/miri/pull/1933 - this.write_uninit(&this.deref_operand(attr_op)?.into())?; + this.write_uninit( + &this.deref_operand_as(attr_op, this.libc_ty_layout("pthread_mutexattr_t")?)?.into(), + )?; Ok(0) } @@ -437,7 +499,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { mutex_get_id(this, mutex_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit(&this.deref_operand(mutex_op)?.into())?; + this.write_uninit( + &this.deref_operand_as(mutex_op, this.libc_ty_layout("pthread_mutex_t")?)?.into(), + )?; // FIXME: delete interpreter state associated with this mutex. Ok(0) @@ -560,7 +624,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { rwlock_get_id(this, rwlock_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit(&this.deref_operand(rwlock_op)?.into())?; + this.write_uninit( + &this.deref_operand_as(rwlock_op, this.libc_ty_layout("pthread_rwlock_t")?)?.into(), + )?; // FIXME: delete interpreter state associated with this rwlock. Ok(0) @@ -609,7 +675,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let clock_id = condattr_get_clock_id(this, attr_op)?; - this.write_scalar(Scalar::from_i32(clock_id), &this.deref_operand(clk_id_op)?.into())?; + this.write_scalar( + Scalar::from_i32(clock_id), + &this.deref_operand_as(clk_id_op, this.machine.layouts.i32)?.into(), + )?; Ok(Scalar::from_i32(0)) } @@ -624,7 +693,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { condattr_get_clock_id(this, attr_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit(&this.deref_operand(attr_op)?.into())?; + this.write_uninit( + &this.deref_operand_as(attr_op, this.libc_ty_layout("pthread_condattr_t")?)?.into(), + )?; Ok(0) } @@ -715,7 +786,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Extract the timeout. let clock_id = cond_get_clock_id(this, cond_op)?; - let duration = match this.read_timespec(&this.deref_operand(abstime_op)?)? { + let duration = match this + .read_timespec(&this.deref_operand_as(abstime_op, this.libc_ty_layout("timespec")?)?)? + { Some(duration) => duration, None => { let einval = this.eval_libc("EINVAL")?; @@ -797,7 +870,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { cond_get_clock_id(this, cond_op)?; // This might lead to false positives, see comment in pthread_mutexattr_destroy - this.write_uninit(&this.deref_operand(cond_op)?.into())?; + this.write_uninit( + &this.deref_operand_as(cond_op, this.libc_ty_layout("pthread_cond_t")?)?.into(), + )?; // FIXME: delete interpreter state associated with this condvar. Ok(0) diff --git a/src/shims/unix/thread.rs b/src/shims/unix/thread.rs index b43682710b..05da4219c6 100644 --- a/src/shims/unix/thread.rs +++ b/src/shims/unix/thread.rs @@ -13,7 +13,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); - let thread_info_place = this.deref_operand(thread)?; + let thread_info_place = this.deref_operand_as(thread, this.libc_ty_layout("pthread_t")?)?; let start_routine = this.read_pointer(start_routine)?; diff --git a/src/shims/windows/dlsym.rs b/src/shims/windows/dlsym.rs index 4b2a90723c..66786fb6fe 100644 --- a/src/shims/windows/dlsym.rs +++ b/src/shims/windows/dlsym.rs @@ -71,7 +71,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let buf = this.read_pointer(buf)?; let n = this.read_scalar(n)?.to_u32()?; let byte_offset = this.read_scalar(byte_offset)?.to_machine_usize(this)?; // is actually a pointer - let io_status_block = this.deref_operand(io_status_block)?; + let io_status_block = this.deref_operand_as( + io_status_block, + this.windows_ty_layout("IO_STATUS_BLOCK")?, + )?; if byte_offset != 0 { throw_unsup_format!( diff --git a/src/shims/windows/foreign_items.rs b/src/shims/windows/foreign_items.rs index e16749c986..8360b70c7d 100644 --- a/src/shims/windows/foreign_items.rs +++ b/src/shims/windows/foreign_items.rs @@ -1,7 +1,6 @@ use std::iter; use rustc_span::Symbol; -use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; use crate::*; @@ -10,8 +9,6 @@ use shims::windows::handle::{EvalContextExt as _, Handle, PseudoHandle}; use shims::windows::sync::EvalContextExt as _; use shims::windows::thread::EvalContextExt as _; -use smallvec::SmallVec; - impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn emulate_foreign_item_by_name( @@ -118,54 +115,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Also called from `page_size` crate. let [system_info] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; - let system_info = this.deref_operand(system_info)?; + let system_info = + this.deref_operand_as(system_info, this.windows_ty_layout("SYSTEM_INFO")?)?; // Initialize with `0`. this.write_bytes_ptr( system_info.ptr, iter::repeat(0u8).take(system_info.layout.size.bytes_usize()), )?; // Set selected fields. - let word_layout = this.machine.layouts.u16; - let dword_layout = this.machine.layouts.u32; - let usize_layout = this.machine.layouts.usize; - - // Using `mplace_field` is error-prone, see: /~https://github.com/rust-lang/miri/issues/2136. - // Pointer fields have different sizes on different targets. - // To avoid all these issue we calculate the offsets ourselves. - let field_sizes = [ - word_layout.size, // 0, wProcessorArchitecture : WORD - word_layout.size, // 1, wReserved : WORD - dword_layout.size, // 2, dwPageSize : DWORD - usize_layout.size, // 3, lpMinimumApplicationAddress : LPVOID - usize_layout.size, // 4, lpMaximumApplicationAddress : LPVOID - usize_layout.size, // 5, dwActiveProcessorMask : DWORD_PTR - dword_layout.size, // 6, dwNumberOfProcessors : DWORD - dword_layout.size, // 7, dwProcessorType : DWORD - dword_layout.size, // 8, dwAllocationGranularity : DWORD - word_layout.size, // 9, wProcessorLevel : WORD - word_layout.size, // 10, wProcessorRevision : WORD - ]; - let field_offsets: SmallVec<[Size; 11]> = field_sizes - .iter() - .copied() - .scan(Size::ZERO, |a, x| { - let res = Some(*a); - *a += x; - res - }) - .collect(); - - // Set page size. - let page_size = system_info.offset(field_offsets[2], dword_layout, &this.tcx)?; - this.write_scalar( - Scalar::from_int(PAGE_SIZE, dword_layout.size), - &page_size.into(), - )?; - // Set number of processors. - let num_cpus = system_info.offset(field_offsets[6], dword_layout, &this.tcx)?; - this.write_scalar( - Scalar::from_int(this.machine.num_cpus, dword_layout.size), - &num_cpus.into(), + this.write_int_fields_named( + &[ + ("dwPageSize", PAGE_SIZE.into()), + ("dwNumberOfProcessors", this.machine.num_cpus.into()), + ], + &system_info, )?; } @@ -357,6 +320,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [console, buffer_info] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_scalar(console)?.to_machine_isize(this)?; + // FIXME: this should use deref_operand_as, but CONSOLE_SCREEN_BUFFER_INFO is not in std this.deref_operand(buffer_info)?; // Indicate an error. // FIXME: we should set last_error, but to what? @@ -433,7 +397,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [console, mode] = this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?; this.read_scalar(console)?.to_machine_isize(this)?; - this.deref_operand(mode)?; + this.deref_operand_as(mode, this.machine.layouts.u32)?; // Indicate an error. this.write_null(dest)?; } diff --git a/src/shims/windows/sync.rs b/src/shims/windows/sync.rs index 8f414d98db..0a24b849e1 100644 --- a/src/shims/windows/sync.rs +++ b/src/shims/windows/sync.rs @@ -7,10 +7,6 @@ use crate::concurrency::sync::{CondvarLock, RwLockMode}; use crate::concurrency::thread::MachineCallback; use crate::*; -const SRWLOCK_ID_OFFSET: u64 = 0; -const INIT_ONCE_ID_OFFSET: u64 = 0; -const CONDVAR_ID_OFFSET: u64 = 0; - impl<'mir, 'tcx> EvalContextExtPriv<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Try to reacquire the lock associated with the condition variable after we @@ -41,6 +37,30 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { Ok(()) } + + fn srwlock_get_id( + &mut self, + rwlock_op: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, RwLockId> { + let this = self.eval_context_mut(); + this.rwlock_get_or_create_id(rwlock_op, this.windows_ty_layout("SRWLOCK")?, 0) + } + + fn init_once_get_id( + &mut self, + init_once_op: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, InitOnceId> { + let this = self.eval_context_mut(); + this.init_once_get_or_create_id(init_once_op, this.windows_ty_layout("INIT_ONCE")?, 0) + } + + fn condvar_get_id( + &mut self, + condvar_op: &OpTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, CondvarId> { + let this = self.eval_context_mut(); + this.condvar_get_or_create_id(condvar_op, this.windows_ty_layout("CONDITION_VARIABLE")?, 0) + } } impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -48,7 +68,7 @@ impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn AcquireSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let id = this.srwlock_get_id(lock_op)?; let active_thread = this.get_active_thread(); if this.rwlock_is_locked(id) { @@ -72,7 +92,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { lock_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let id = this.srwlock_get_id(lock_op)?; let active_thread = this.get_active_thread(); if this.rwlock_is_locked(id) { @@ -86,7 +106,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn ReleaseSRWLockExclusive(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let id = this.srwlock_get_id(lock_op)?; let active_thread = this.get_active_thread(); if !this.rwlock_writer_unlock(id, active_thread) { @@ -101,7 +121,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn AcquireSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let id = this.srwlock_get_id(lock_op)?; let active_thread = this.get_active_thread(); if this.rwlock_is_write_locked(id) { @@ -118,7 +138,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { lock_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let id = this.srwlock_get_id(lock_op)?; let active_thread = this.get_active_thread(); if this.rwlock_is_write_locked(id) { @@ -131,7 +151,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn ReleaseSRWLockShared(&mut self, lock_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let id = this.srwlock_get_id(lock_op)?; let active_thread = this.get_active_thread(); if !this.rwlock_reader_unlock(id, active_thread) { @@ -154,9 +174,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let this = self.eval_context_mut(); let active_thread = this.get_active_thread(); - let id = this.init_once_get_or_create_id(init_once_op, INIT_ONCE_ID_OFFSET)?; + let id = this.init_once_get_id(init_once_op)?; let flags = this.read_scalar(flags_op)?.to_u32()?; - let pending_place = this.deref_operand(pending_op)?.into(); + let pending_place = this.deref_operand_as(pending_op, this.machine.layouts.u32)?.into(); let context = this.read_pointer(context_op)?; if flags != 0 { @@ -229,7 +249,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let id = this.init_once_get_or_create_id(init_once_op, INIT_ONCE_ID_OFFSET)?; + let id = this.init_once_get_id(init_once_op)?; let flags = this.read_scalar(flags_op)?.to_u32()?; let context = this.read_pointer(context_op)?; @@ -372,8 +392,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?; - let lock_id = this.rwlock_get_or_create_id(lock_op, SRWLOCK_ID_OFFSET)?; + let condvar_id = this.condvar_get_id(condvar_op)?; + let lock_id = this.srwlock_get_id(lock_op)?; let timeout_ms = this.read_scalar(timeout_op)?.to_u32()?; let flags = this.read_scalar(flags_op)?.to_u32()?; @@ -456,7 +476,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn WakeConditionVariable(&mut self, condvar_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?; + let condvar_id = this.condvar_get_id(condvar_op)?; if let Some((thread, lock)) = this.condvar_signal(condvar_id) { if let CondvarLock::RwLock { id, mode } = lock { @@ -475,7 +495,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { condvar_op: &OpTy<'tcx, Provenance>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?; + let condvar_id = this.condvar_get_id(condvar_op)?; while let Some((thread, lock)) = this.condvar_signal(condvar_id) { if let CondvarLock::RwLock { id, mode } = lock { diff --git a/src/shims/windows/thread.rs b/src/shims/windows/thread.rs index 5ed0cb92f9..0a1016f708 100644 --- a/src/shims/windows/thread.rs +++ b/src/shims/windows/thread.rs @@ -29,7 +29,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let thread = if this.ptr_is_null(this.read_pointer(thread_op)?)? { None } else { - let thread_info_place = this.deref_operand(thread_op)?; + let thread_info_place = this.deref_operand_as(thread_op, this.machine.layouts.u32)?; Some(thread_info_place) };