diff --git a/.appveyor.yml b/.appveyor.yml index e5c2f4fb72..294ef26be0 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -46,6 +46,7 @@ build_script: test_script: - set RUST_TEST_NOCAPTURE=1 - set RUST_BACKTRACE=1 + - set CARGO_INCREMENTAL=0 # Test host miri: 32bit Windows - cargo miri setup - set MIRI_SYSROOT=%USERPROFILE%\AppData\Local\rust-lang\miri\cache\HOST diff --git a/.travis.yml b/.travis.yml index 137ae4fe66..a074d6b14d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,7 @@ env: global: - RUST_TEST_NOCAPTURE=1 - RUST_BACKTRACE=1 + - CARGO_INCREMENTAL=0 before_script: # Compute the rust version we use. We do not use "language: rust" to have more control here. diff --git a/miri b/miri index 0cda9e8092..8cd2cfc3ae 100755 --- a/miri +++ b/miri @@ -49,7 +49,10 @@ fi # We enable debug-assertions to get tracing. # We enable line-only debuginfo for backtraces. export RUSTFLAGS="-C link-args=-Wl,-rpath,$LIBDIR -C debug-assertions -C debuginfo=1 $RUSTC_EXTRA_FLAGS" -export CARGO_INCREMENTAL=1 +if [ -z "$CARGO_INCREMENTAL" ]; then + # Default CARGO_INCREMENTAL to 1. + export CARGO_INCREMENTAL=1 +fi ## Helper functions diff --git a/rust-version b/rust-version index a812b46de1..e3dc200835 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -9a12971da5c08f9a95d54bdaef5cd83698ed4509 +537ccdf3ac44c8c7a8d36cbdbe6fb224afabb7ae diff --git a/src/diagnostics.rs b/src/diagnostics.rs index a528960cb2..9ff4340211 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -129,15 +129,12 @@ fn report_msg<'tcx, 'mir>( err.help(help); } // Add backtrace - let frames = ecx.generate_stacktrace(None); - // We iterate with indices because we need to look at the next frame (the caller). - for idx in 0..frames.len() { - let frame_info = &frames[idx]; - let call_site_is_local = frames - .get(idx + 1) - .map_or(false, |caller_info| caller_info.instance.def_id().is_local()); - if call_site_is_local { - err.span_note(frame_info.call_site, &frame_info.to_string()); + let frames = ecx.generate_stacktrace(); + for (idx, frame_info) in frames.iter().enumerate() { + let is_local = frame_info.instance.def_id().is_local(); + // No span for non-local frames and the first frame (which is the error site). + if is_local && idx > 0 { + err.span_note(frame_info.span, &frame_info.to_string()); } else { err.note(&frame_info.to_string()); } diff --git a/src/eval.rs b/src/eval.rs index a4867bd5de..46e66bc0a8 100644 --- a/src/eval.rs +++ b/src/eval.rs @@ -6,7 +6,7 @@ use std::convert::TryFrom; use rand::rngs::StdRng; use rand::SeedableRng; -use rustc_middle::ty::layout::LayoutOf; +use rustc_target::abi::LayoutOf; use rustc_middle::ty::{self, TyCtxt}; use rustc_hir::def_id::DefId; diff --git a/src/helpers.rs b/src/helpers.rs index 15f1b286de..9f46a0c1ce 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -4,13 +4,9 @@ use std::mem; use log::trace; use rustc_middle::mir; -use rustc_middle::ty::{ - self, - layout::{self, LayoutOf, Size, TyAndLayout}, - List, TyCtxt, -}; +use rustc_middle::ty::{self, List, TyCtxt, layout::TyAndLayout}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; -use rustc_span::source_map::DUMMY_SP; +use rustc_target::abi::{LayoutOf, Size, FieldsShape, Variants}; use rand::RngCore; @@ -73,17 +69,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx .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 @@ -93,6 +95,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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) @@ -115,7 +124,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> { let this = self.eval_context_mut(); let place = mir::Place { local: local, projection: List::empty() }; - this.eval_place(&place) + this.eval_place(place) } /// Generate some random bytes, and write them to `dest`. @@ -157,13 +166,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // Push frame. let mir = &*this.load_mir(f.def, None)?; - let span = this - .stack() - .last() - .and_then(Frame::current_source_info) - .map(|si| si.span) - .unwrap_or(DUMMY_SP); - this.push_stack_frame(f, span, mir, dest, stack_pop)?; + this.push_stack_frame(f, mir, dest, stack_pop)?; // Initialize arguments. let mut callee_args = this.frame().body.args_iter(); @@ -292,7 +295,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // walking this value, we have to make sure it is not a // `Variants::Multiple`. match v.layout.variants { - layout::Variants::Multiple { .. } => { + Variants::Multiple { .. } => { // A multi-variant enum, or generator, or so. // Treat this like a union: without reading from memory, // we cannot determine the variant we are in. Reading from @@ -302,7 +305,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx // `UnsafeCell` action. (self.unsafe_cell_action)(v) } - layout::Variants::Single { .. } => { + Variants::Single { .. } => { // Proceed further, try to find where exactly that `UnsafeCell` // is hiding. self.walk_value(v) @@ -318,19 +321,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx fields: impl Iterator<Item = InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>, ) -> InterpResult<'tcx> { match place.layout.fields { - layout::FieldPlacement::Array { .. } => { + FieldsShape::Array { .. } => { // For the array layout, we know the iterator will yield sorted elements so // we can avoid the allocation. self.walk_aggregate(place, fields) } - layout::FieldPlacement::Arbitrary { .. } => { + FieldsShape::Arbitrary { .. } => { // Gather the subplaces and sort them before visiting. let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?; places.sort_by_key(|place| place.ptr.assert_ptr().offset); self.walk_aggregate(place, places.into_iter().map(Ok)) } - layout::FieldPlacement::Union { .. } => { + FieldsShape::Union { .. } => { // Uh, what? bug!("a union is not an aggregate we should ever visit") } @@ -350,7 +353,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx } } - // 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, @@ -439,7 +442,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx })? } 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) })? diff --git a/src/intptrcast.rs b/src/intptrcast.rs index 8eb28e4f47..ac27138d76 100644 --- a/src/intptrcast.rs +++ b/src/intptrcast.rs @@ -6,9 +6,8 @@ use log::trace; use rand::Rng; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::layout::HasDataLayout; use rustc_mir::interpret::{AllocCheck, AllocId, InterpResult, Memory, Machine, Pointer, PointerArithmetic}; -use rustc_target::abi::Size; +use rustc_target::abi::{Size, HasDataLayout}; use crate::{Evaluator, Tag, STACK_ADDR}; diff --git a/src/machine.rs b/src/machine.rs index 4b7f3a7656..f794453228 100644 --- a/src/machine.rs +++ b/src/machine.rs @@ -11,14 +11,10 @@ use log::trace; use rand::rngs::StdRng; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::mir; -use rustc_middle::ty::{ - self, - layout::{LayoutOf, Size}, - Ty, -}; +use rustc_middle::{mir, ty}; +use rustc_target::abi::{LayoutOf, Size}; use rustc_ast::attr; -use rustc_span::{source_map::Span, symbol::{sym, Symbol}}; +use rustc_span::symbol::{sym, Symbol}; use crate::*; @@ -253,7 +249,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { #[inline(always)] fn find_mir_or_eval_fn( ecx: &mut InterpCx<'mir, 'tcx, Self>, - _span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Tag>], ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>, @@ -276,13 +271,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { #[inline(always)] fn call_intrinsic( ecx: &mut rustc_mir::interpret::InterpCx<'mir, 'tcx, Self>, - span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Tag>], ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>, unwind: Option<mir::BasicBlock>, ) -> InterpResult<'tcx> { - ecx.call_intrinsic(span, instance, args, ret, unwind) + ecx.call_intrinsic(instance, args, ret, unwind) } #[inline(always)] @@ -305,7 +299,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for Evaluator<'tcx> { bin_op: mir::BinOp, left: ImmTy<'tcx, Tag>, right: ImmTy<'tcx, Tag>, - ) -> InterpResult<'tcx, (Scalar<Tag>, bool, Ty<'tcx>)> { + ) -> InterpResult<'tcx, (Scalar<Tag>, bool, ty::Ty<'tcx>)> { ecx.binary_ptr_op(bin_op, left, right) } diff --git a/src/operator.rs b/src/operator.rs index 2232be713e..a28a0098e9 100644 --- a/src/operator.rs +++ b/src/operator.rs @@ -2,11 +2,8 @@ use std::convert::TryFrom; use log::trace; -use rustc_middle::mir; -use rustc_middle::ty::{ - layout::{LayoutOf, Size}, - Ty, -}; +use rustc_middle::{mir, ty::Ty}; +use rustc_target::abi::{LayoutOf, Size}; use crate::*; diff --git a/src/range_map.rs b/src/range_map.rs index 1d12d8a1ba..16ad5fd7c2 100644 --- a/src/range_map.rs +++ b/src/range_map.rs @@ -7,7 +7,7 @@ use std::ops; -use rustc_middle::ty::layout::Size; +use rustc_target::abi::Size; #[derive(Clone, Debug)] struct Elem<T> { diff --git a/src/shims/env.rs b/src/shims/env.rs index d30e953cf5..4401682722 100644 --- a/src/shims/env.rs +++ b/src/shims/env.rs @@ -2,14 +2,12 @@ use std::ffi::{OsString, OsStr}; use std::env; use std::convert::TryFrom; -use crate::stacked_borrows::Tag; -use crate::rustc_target::abi::LayoutOf; -use crate::*; - +use rustc_target::abi::{Size, LayoutOf}; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::layout::Size; use rustc_mir::interpret::Pointer; +use crate::*; + /// Check whether an operation that writes to a target buffer was successful. /// Accordingly select return value. /// Local helper function to be used in Windows shims. @@ -143,7 +141,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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 } diff --git a/src/shims/foreign_items.rs b/src/shims/foreign_items.rs index da2f9d439c..7e7f17b0db 100644 --- a/src/shims/foreign_items.rs +++ b/src/shims/foreign_items.rs @@ -4,9 +4,8 @@ mod posix; use std::{convert::{TryInto, TryFrom}, iter}; use rustc_hir::def_id::DefId; -use rustc_middle::mir; -use rustc_middle::ty; -use rustc_middle::ty::layout::{Align, Size}; +use rustc_middle::{mir, ty}; +use rustc_target::abi::{Align, Size}; use rustc_apfloat::Float; use rustc_span::symbol::sym; use rustc_ast::attr; diff --git a/src/shims/foreign_items/posix.rs b/src/shims/foreign_items/posix.rs index 2816159298..c9fd59c693 100644 --- a/src/shims/foreign_items/posix.rs +++ b/src/shims/foreign_items/posix.rs @@ -7,7 +7,7 @@ use log::trace; use crate::*; use rustc_middle::mir; -use rustc_middle::ty::layout::{Align, LayoutOf, Size}; +use rustc_target::abi::{Align, LayoutOf, Size}; impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { diff --git a/src/shims/foreign_items/windows.rs b/src/shims/foreign_items/windows.rs index f39d477f82..276dd8fda9 100644 --- a/src/shims/foreign_items/windows.rs +++ b/src/shims/foreign_items/windows.rs @@ -1,8 +1,10 @@ -use crate::*; -use rustc_middle::mir; -use rustc_middle::ty::layout::Size; use std::iter; +use rustc_middle::mir; +use rustc_target::abi::Size; + +use crate::*; + impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { fn emulate_foreign_item_by_name( @@ -167,6 +169,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx )?; } + // Time related shims + "GetSystemTimeAsFileTime" => { + this.GetSystemTimeAsFileTime(args[0])?; + } + // Miscellaneous "SystemFunction036" => { // The actual name of 'RtlGenRandom' diff --git a/src/shims/fs.rs b/src/shims/fs.rs index 89d067be86..52244dcfc8 100644 --- a/src/shims/fs.rs +++ b/src/shims/fs.rs @@ -6,7 +6,7 @@ use std::path::Path; use std::time::SystemTime; use rustc_data_structures::fx::FxHashMap; -use rustc_middle::ty::layout::{Align, LayoutOf, Size}; +use rustc_target::abi::{Align, LayoutOf, Size}; use crate::stacked_borrows::Tag; use crate::*; diff --git a/src/shims/intrinsics.rs b/src/shims/intrinsics.rs index 641b8b2563..844eac398d 100644 --- a/src/shims/intrinsics.rs +++ b/src/shims/intrinsics.rs @@ -1,11 +1,9 @@ use std::iter; use std::convert::TryFrom; -use rustc_middle::mir; -use rustc_middle::ty; -use rustc_middle::ty::layout::{Align, LayoutOf}; +use rustc_middle::{mir, ty}; use rustc_apfloat::Float; -use rustc_span::source_map::Span; +use rustc_target::abi::{Align, LayoutOf}; use crate::*; @@ -13,14 +11,13 @@ impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tc pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> { fn call_intrinsic( &mut self, - span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx, Tag>], ret: Option<(PlaceTy<'tcx, Tag>, mir::BasicBlock)>, unwind: Option<mir::BasicBlock>, ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - if this.emulate_intrinsic(span, instance, args, ret)? { + if this.emulate_intrinsic(instance, args, ret)? { return Ok(()); } let substs = instance.substs; @@ -217,8 +214,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx this.write_immediate(*val, place.into())?; } - "breakpoint" => unimplemented!(), // halt miri - #[rustfmt::skip] | "copy" | "copy_nonoverlapping" diff --git a/src/shims/os_str.rs b/src/shims/os_str.rs index 704994da4b..c24d6df41e 100644 --- a/src/shims/os_str.rs +++ b/src/shims/os_str.rs @@ -9,7 +9,7 @@ use std::os::unix::ffi::{OsStrExt, OsStringExt}; #[cfg(windows)] use std::os::windows::ffi::{OsStrExt, OsStringExt}; -use rustc_middle::ty::layout::LayoutOf; +use rustc_target::abi::LayoutOf; use crate::*; diff --git a/src/shims/panic.rs b/src/shims/panic.rs index 77741b7cca..33e47147a3 100644 --- a/src/shims/panic.rs +++ b/src/shims/panic.rs @@ -13,9 +13,8 @@ use log::trace; -use rustc_middle::mir; -use rustc_middle::ty::{self, layout::LayoutOf}; -use rustc_target::spec::PanicStrategy; +use rustc_middle::{mir, ty}; +use rustc_target::{spec::PanicStrategy, abi::LayoutOf}; use crate::*; @@ -51,7 +50,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - trace!("miri_start_panic: {:?}", this.frame().span); + trace!("miri_start_panic: {:?}", this.frame().instance); // Get the raw pointer stored in arg[0] (the panic payload). let payload = this.read_scalar(args[0])?.not_undef()?; @@ -133,7 +132,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx if let (true, Some(catch_unwind)) = (unwinding, extra.catch_unwind.take()) { // We've just popped a frame that was pushed by `try`, // and we are unwinding, so we should catch that. - trace!("unwinding: found catch_panic frame during unwinding: {:?}", this.frame().span); + trace!("unwinding: found catch_panic frame during unwinding: {:?}", this.frame().instance); // We set the return value of `try` to 1, since there was a panic. this.write_scalar(Scalar::from_i32(1), catch_unwind.dest)?; diff --git a/src/shims/time.rs b/src/shims/time.rs index 58db60e516..a7fca5e0dd 100644 --- a/src/shims/time.rs +++ b/src/shims/time.rs @@ -1,9 +1,11 @@ use std::time::{Duration, SystemTime, Instant}; use std::convert::TryFrom; +use rustc_target::abi::LayoutOf; + use crate::stacked_borrows::Tag; use crate::*; -use helpers::immty_from_int_checked; +use helpers::{immty_from_int_checked, immty_from_uint_checked}; /// 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> { @@ -85,6 +87,34 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx 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())? + Duration::from_secs(SECONDS_TO_UNIX_EPOCH); + let duration_ticks = u64::try_from(duration.as_nanos() / u128::from(NANOS_PER_INTERVAL)) + .map_err(|_| err_unsup_format!("programs running more than 2^64 Windows ticks after the Windows epoch 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(); diff --git a/src/shims/tls.rs b/src/shims/tls.rs index 76f946f724..36ad4bd9b6 100644 --- a/src/shims/tls.rs +++ b/src/shims/tls.rs @@ -4,8 +4,8 @@ use std::collections::BTreeMap; use log::trace; -use rustc_middle::{ty, ty::layout::{Size, HasDataLayout}}; -use rustc_target::abi::LayoutOf; +use rustc_middle::ty; +use rustc_target::abi::{LayoutOf, Size, HasDataLayout}; use crate::{HelpersEvalContextExt, InterpResult, MPlaceTy, Scalar, StackPopCleanup, Tag}; diff --git a/src/stacked_borrows.rs b/src/stacked_borrows.rs index 90920069c5..89b2a8bb3e 100644 --- a/src/stacked_borrows.rs +++ b/src/stacked_borrows.rs @@ -10,7 +10,8 @@ use log::trace; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::RetagKind; -use rustc_middle::ty::{self, layout::Size}; +use rustc_middle::ty; +use rustc_target::abi::Size; use rustc_hir::Mutability; use crate::*; diff --git a/tests/compile-fail/deallocate-bad-alignment.rs b/tests/compile-fail/deallocate-bad-alignment.rs index f2cd87bac6..9b5ee9a934 100644 --- a/tests/compile-fail/deallocate-bad-alignment.rs +++ b/tests/compile-fail/deallocate-bad-alignment.rs @@ -1,15 +1,10 @@ -#![feature(allocator_api)] - -extern crate alloc; - -use alloc::alloc::Global; -use std::alloc::{AllocRef, Layout}; +use std::alloc::{alloc, dealloc, realloc, Layout}; // error-pattern: allocation has size 1 and alignment 1, but gave size 1 and alignment 2 fn main() { unsafe { - let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap().0; - Global.dealloc(x, Layout::from_size_align_unchecked(1, 2)); + let x = alloc(Layout::from_size_align_unchecked(1, 1)); + dealloc(x, Layout::from_size_align_unchecked(1, 2)); } } diff --git a/tests/compile-fail/deallocate-bad-size.rs b/tests/compile-fail/deallocate-bad-size.rs index 498a662518..39a0d48c8b 100644 --- a/tests/compile-fail/deallocate-bad-size.rs +++ b/tests/compile-fail/deallocate-bad-size.rs @@ -1,15 +1,10 @@ -#![feature(allocator_api)] - -extern crate alloc; - -use alloc::alloc::Global; -use std::alloc::{AllocRef, Layout}; +use std::alloc::{alloc, dealloc, realloc, Layout}; // error-pattern: allocation has size 1 and alignment 1, but gave size 2 and alignment 1 fn main() { unsafe { - let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap().0; - Global.dealloc(x, Layout::from_size_align_unchecked(2, 1)); + let x = alloc(Layout::from_size_align_unchecked(1, 1)); + dealloc(x, Layout::from_size_align_unchecked(2, 1)); } } diff --git a/tests/compile-fail/deallocate-twice.rs b/tests/compile-fail/deallocate-twice.rs index a851d75b9d..3c5e8e9636 100644 --- a/tests/compile-fail/deallocate-twice.rs +++ b/tests/compile-fail/deallocate-twice.rs @@ -1,16 +1,11 @@ -#![feature(allocator_api)] - -extern crate alloc; - -use alloc::alloc::Global; -use std::alloc::{AllocRef, Layout}; +use std::alloc::{alloc, dealloc, realloc, Layout}; // error-pattern: dereferenced after this allocation got freed fn main() { unsafe { - let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap().0; - Global.dealloc(x, Layout::from_size_align_unchecked(1, 1)); - Global.dealloc(x, Layout::from_size_align_unchecked(1, 1)); + let x = alloc(Layout::from_size_align_unchecked(1, 1)); + dealloc(x, Layout::from_size_align_unchecked(1, 1)); + dealloc(x, Layout::from_size_align_unchecked(1, 1)); } } diff --git a/tests/compile-fail/never_transmute_void.rs b/tests/compile-fail/never_transmute_void.rs index 2a822ab1b5..5e9e2ac204 100644 --- a/tests/compile-fail/never_transmute_void.rs +++ b/tests/compile-fail/never_transmute_void.rs @@ -7,12 +7,12 @@ enum Void {} fn f(v: Void) -> ! { - match v {} //~ ERROR entering unreachable code + match v {} //~ ERROR entering unreachable code } fn main() { let v: Void = unsafe { std::mem::transmute::<(), Void>(()) }; - f(v); //~ inside call to `f` + f(v); //~ inside `main` } diff --git a/tests/compile-fail/reallocate-bad-size.rs b/tests/compile-fail/reallocate-bad-size.rs index a62c1adae7..bbdef4421b 100644 --- a/tests/compile-fail/reallocate-bad-size.rs +++ b/tests/compile-fail/reallocate-bad-size.rs @@ -1,15 +1,10 @@ -#![feature(allocator_api)] - -extern crate alloc; - -use alloc::alloc::Global; -use std::alloc::{AllocRef, Layout}; +use std::alloc::{alloc, dealloc, realloc, Layout}; // error-pattern: allocation has size 1 and alignment 1, but gave size 2 and alignment 1 fn main() { unsafe { - let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap().0; - Global.realloc(x, Layout::from_size_align_unchecked(2, 1), 1).unwrap(); + let x = alloc(Layout::from_size_align_unchecked(1, 1)); + realloc(x, Layout::from_size_align_unchecked(2, 1), 1); } } diff --git a/tests/compile-fail/reallocate-change-alloc.rs b/tests/compile-fail/reallocate-change-alloc.rs index 0d4b60e0a3..8130d72dee 100644 --- a/tests/compile-fail/reallocate-change-alloc.rs +++ b/tests/compile-fail/reallocate-change-alloc.rs @@ -1,14 +1,9 @@ -#![feature(allocator_api)] - -extern crate alloc; - -use alloc::alloc::Global; -use std::alloc::{AllocRef, Layout}; +use std::alloc::{alloc, dealloc, realloc, Layout}; fn main() { unsafe { - let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap().0; - Global.realloc(x, Layout::from_size_align_unchecked(1, 1), 1).unwrap(); - let _z = *(x.as_ptr() as *mut u8); //~ ERROR dereferenced after this allocation got freed + let x = alloc(Layout::from_size_align_unchecked(1, 1)); + realloc(x, Layout::from_size_align_unchecked(1, 1), 1); + let _z = *x; //~ ERROR dereferenced after this allocation got freed } } diff --git a/tests/compile-fail/reallocate-dangling.rs b/tests/compile-fail/reallocate-dangling.rs index 9661d7e966..702ddc0724 100644 --- a/tests/compile-fail/reallocate-dangling.rs +++ b/tests/compile-fail/reallocate-dangling.rs @@ -1,16 +1,11 @@ -#![feature(allocator_api)] - -extern crate alloc; - -use alloc::alloc::Global; -use std::alloc::{AllocRef, Layout}; +use std::alloc::{alloc, dealloc, realloc, Layout}; // error-pattern: dereferenced after this allocation got freed fn main() { unsafe { - let x = Global.alloc(Layout::from_size_align_unchecked(1, 1)).unwrap().0; - Global.dealloc(x, Layout::from_size_align_unchecked(1, 1)); - Global.realloc(x, Layout::from_size_align_unchecked(1, 1), 1).unwrap(); + let x = alloc(Layout::from_size_align_unchecked(1, 1)); + dealloc(x, Layout::from_size_align_unchecked(1, 1)); + realloc(x, Layout::from_size_align_unchecked(1, 1), 1); } } diff --git a/tests/run-pass/heap_allocator.rs b/tests/run-pass/heap_allocator.rs index 8077be405f..c2fcfea58c 100644 --- a/tests/run-pass/heap_allocator.rs +++ b/tests/run-pass/heap_allocator.rs @@ -1,7 +1,7 @@ #![feature(allocator_api)] use std::ptr::NonNull; -use std::alloc::{Global, AllocRef, Layout, System}; +use std::alloc::{Global, AllocRef, Layout, System, AllocInit, ReallocPlacement}; use std::slice; fn check_alloc<T: AllocRef>(mut allocator: T) { unsafe { @@ -9,28 +9,29 @@ fn check_alloc<T: AllocRef>(mut allocator: T) { unsafe { let layout = Layout::from_size_align(20, align).unwrap(); for _ in 0..32 { - let a = allocator.alloc(layout).unwrap().0; + let a = allocator.alloc(layout, AllocInit::Uninitialized).unwrap().ptr; assert_eq!(a.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); allocator.dealloc(a, layout); } - let p1 = allocator.alloc_zeroed(layout).unwrap().0; + let p1 = allocator.alloc(layout, AllocInit::Zeroed).unwrap().ptr; assert_eq!(p1.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); - let p2 = allocator.realloc(p1, layout, 40).unwrap().0; + // old size < new size + let p2 = allocator.grow(p1, layout, 40, ReallocPlacement::MayMove, AllocInit::Uninitialized).unwrap().ptr; let layout = Layout::from_size_align(40, align).unwrap(); assert_eq!(p2.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); let slice = slice::from_raw_parts(p2.as_ptr(), 20); assert_eq!(&slice, &[0_u8; 20]); // old size == new size - let p3 = allocator.realloc(p2, layout, 40).unwrap().0; + let p3 = allocator.grow(p2, layout, 40, ReallocPlacement::MayMove, AllocInit::Uninitialized).unwrap().ptr; assert_eq!(p3.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); let slice = slice::from_raw_parts(p3.as_ptr(), 20); assert_eq!(&slice, &[0_u8; 20]); // old size > new size - let p4 = allocator.realloc(p3, layout, 10).unwrap().0; + let p4 = allocator.shrink(p3, layout, 10, ReallocPlacement::MayMove).unwrap().ptr; let layout = Layout::from_size_align(10, align).unwrap(); assert_eq!(p4.as_ptr() as usize % align, 0, "pointer is incorrectly aligned"); let slice = slice::from_raw_parts(p4.as_ptr(), 10); @@ -46,7 +47,7 @@ fn check_align_requests<T: AllocRef>(mut allocator: T) { let iterations = 32; unsafe { let pointers: Vec<_> = (0..iterations).map(|_| { - allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap().0 + allocator.alloc(Layout::from_size_align(size, align).unwrap(), AllocInit::Uninitialized).unwrap().ptr }).collect(); for &ptr in &pointers { assert_eq!((ptr.as_ptr() as usize) % align, 0, @@ -67,7 +68,7 @@ fn global_to_box() { let l = Layout::new::<T>(); // allocate manually with global allocator, then turn into Box and free there unsafe { - let ptr = Global.alloc(l).unwrap().0.as_ptr() as *mut T; + let ptr = Global.alloc(l, AllocInit::Uninitialized).unwrap().ptr.as_ptr() as *mut T; let b = Box::from_raw(ptr); drop(b); } diff --git a/tests/run-pass/time.rs b/tests/run-pass/time.rs index bbe8b4011d..a9ca28161c 100644 --- a/tests/run-pass/time.rs +++ b/tests/run-pass/time.rs @@ -1,18 +1,40 @@ -// ignore-windows: TODO clock shims are not implemented on Windows // compile-flags: -Zmiri-disable-isolation use std::time::{SystemTime, Instant}; fn main() { + // Check `SystemTime`. let now1 = SystemTime::now(); // Do some work to make time pass. for _ in 0..10 { drop(vec![42]); } let now2 = SystemTime::now(); assert!(now2 > now1); + let diff = now2.duration_since(now1).unwrap(); + assert_eq!(now1 + diff, now2); + assert_eq!(now2 - diff, now1); + // Sanity-check the time we got. + let seconds_since_epoch = now1.duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + let years_since_epoch = seconds_since_epoch / 3600 / 24 / 365; + let year = 1970 + years_since_epoch; + assert!(2020 <= year && year < 2100); - 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); + // Check `Instant`. + #[cfg(not(windows))] // `Instant` shims not yet implemented on Windows + { + 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_eq!(now1 + diff, now2); + assert_eq!(now2 - diff, now1); + // Sanity-check the difference we got. + assert!(diff.as_micros() > 1); + assert!(diff.as_micros() < 1_000_000); + } + } }