.not_undef()
}
+ /// Helper function to get a `libc` constant as an `i32`.
+ fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
+ // TODO: Cache the result.
+ self.eval_libc(name)?.to_i32()
+ }
+
/// Helper function to get a `windows` constant as a `Scalar`.
- fn eval_windows(&mut self, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
+ fn eval_windows(&mut self, module: &str, name: &str) -> InterpResult<'tcx, Scalar<Tag>> {
self.eval_context_mut()
- .eval_path_scalar(&["std", "sys", "windows", "c", name])?
+ .eval_path_scalar(&["std", "sys", "windows", module, name])?
.not_undef()
}
- /// Helper function to get a `libc` constant as an `i32`.
- fn eval_libc_i32(&mut self, name: &str) -> InterpResult<'tcx, i32> {
+ /// Helper function to get a `windows` constant as an `u64`.
+ fn eval_windows_u64(&mut self, module: &str, name: &str) -> InterpResult<'tcx, u64> {
// TODO: Cache the result.
- self.eval_libc(name)?.to_i32()
+ self.eval_windows(module, name)?.to_u64()
}
/// Helper function to get the `TyAndLayout` of a `libc` type
this.layout_of(ty)
}
+ /// Helper function to get the `TyAndLayout` of a `windows` type
+ fn windows_ty_layout(&mut self, name: &str) -> InterpResult<'tcx, TyAndLayout<'tcx>> {
+ let this = self.eval_context_mut();
+ let ty = this.resolve_path(&["std", "sys", "windows", "c", name]).monomorphic_ty(*this.tcx);
+ this.layout_of(ty)
+ }
+
/// Write a 0 of the appropriate size to `dest`.
fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
}
}
- // Writes several `ImmTy`s contiguosly into memory. This is useful when you have to pack
+ // Writes several `ImmTy`s contiguously into memory. This is useful when you have to pack
// different values into a struct.
fn write_packed_immediates(
&mut self,
})?
} else if target_os == "windows" {
// FIXME: we have to finish implementing the Windows equivalent of this.
- this.eval_windows(match e.kind() {
+ this.eval_windows("c", match e.kind() {
NotFound => "ERROR_FILE_NOT_FOUND",
_ => throw_unsup_format!("io error {} cannot be transformed into a raw os error", e)
})?
windows_check_buffer_size(this.write_os_str_to_wide_str(&var, buf_ptr, buf_size)?)
}
None => {
- let envvar_not_found = this.eval_windows("ERROR_ENVVAR_NOT_FOUND")?;
+ let envvar_not_found = this.eval_windows("c", "ERROR_ENVVAR_NOT_FOUND")?;
this.set_last_error(envvar_not_found)?;
0 // return zero upon failure
}
)?;
}
+ // Time related shims
+ "GetSystemTimeAsFileTime" => {
+ this.GetSystemTimeAsFileTime(args[0])?;
+ }
+
// Miscellaneous
"SystemFunction036" => {
// The actual name of 'RtlGenRandom'
use crate::stacked_borrows::Tag;
use crate::*;
-use helpers::immty_from_int_checked;
+use helpers::{immty_from_int_checked, immty_from_uint_checked};
+
+use rustc_middle::ty::layout::LayoutOf;
/// Returns the time elapsed between the provided time and the unix epoch as a `Duration`.
pub fn system_time_to_duration<'tcx>(time: &SystemTime) -> InterpResult<'tcx, Duration> {
Ok(0)
}
+ #[allow(non_snake_case)]
+ fn GetSystemTimeAsFileTime(&mut self, LPFILETIME_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx> {
+ let this = self.eval_context_mut();
+
+ this.assert_target_os("windows", "GetSystemTimeAsFileTime");
+ this.check_no_isolation("GetSystemTimeAsFileTime")?;
+
+ 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")?;
+ let NANOS_PER_INTERVAL = NANOS_PER_SEC / INTERVALS_PER_SEC;
+ let SECONDS_TO_UNIX_EPOCH = INTERVALS_TO_UNIX_EPOCH / INTERVALS_PER_SEC;
+
+ let duration = system_time_to_duration(&SystemTime::now())?
+ .checked_add(Duration::from_secs(SECONDS_TO_UNIX_EPOCH))
+ .unwrap();
+ let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL))
+ .map_err(|_| err_unsup_format!("programs running longer than 2^64 ticks are not supported"))?;
+
+ let dwLowDateTime = u32::try_from(duration_ticks & 0x00000000FFFFFFFF).unwrap();
+ let dwHighDateTime = u32::try_from((duration_ticks & 0xFFFFFFFF00000000) >> 32).unwrap();
+ let DWORD_tylayout = this.layout_of(this.tcx.types.u32)?;
+ let imms = [
+ immty_from_uint_checked(dwLowDateTime, DWORD_tylayout)?,
+ immty_from_uint_checked(dwHighDateTime, DWORD_tylayout)?,
+ ];
+ this.write_packed_immediates(this.deref_operand(LPFILETIME_op)?, &imms)?;
+ Ok(())
+ }
+
fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
let this = self.eval_context_ref();
-// ignore-windows: TODO clock shims are not implemented on Windows
// compile-flags: -Zmiri-disable-isolation
use std::time::{SystemTime, Instant};
assert_eq!(now1 + diff, now2);
assert_eq!(now2 - diff, now1);
- let now1 = Instant::now();
- // Do some work to make time pass.
- for _ in 0..10 { drop(vec![42]); }
- let now2 = Instant::now();
- assert!(now2 > now1);
-
- #[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
+ #[cfg(not(windows))] // `Instant` shims not yet implemented on Windows
{
- let diff = now2.duration_since(now1);
- assert!(diff.as_micros() > 0);
- assert_eq!(now1 + diff, now2);
- assert_eq!(now2 - diff, now1);
+ let now1 = Instant::now();
+ // Do some work to make time pass.
+ for _ in 0..10 { drop(vec![42]); }
+ let now2 = Instant::now();
+ assert!(now2 > now1);
+
+ #[cfg(target_os = "linux")] // TODO: macOS does not support Instant subtraction
+ {
+ let diff = now2.duration_since(now1);
+ assert!(diff.as_micros() > 0);
+ assert_eq!(now1 + diff, now2);
+ assert_eq!(now2 - diff, now1);
+ }
}
}