Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rust-lang/miri
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d1e06b429812916e5fc3129bff992d37639d9da4
Choose a base ref
...
head repository: rust-lang/miri
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 147ea8f400de3ca529abcb5eb7b65f84a4896ae9
Choose a head ref

Commits on Mar 31, 2020

  1. Verified

    This commit was signed with the committer’s verified signature.
    jeremystucki Jeremy Stucki
    Copy the full SHA
    62eaecd View commit details
  2. add TODO

    RalfJung committed Mar 31, 2020
    Copy the full SHA
    26b5012 View commit details
  3. Auto merge of #1287 - RalfJung:time-sub, r=RalfJung

    test subtracting SystemTime and Instant
    bors committed Mar 31, 2020
    Copy the full SHA
    552775b View commit details

Commits on Apr 1, 2020

  1. Copy the full SHA
    b3f9e53 View commit details
  2. remove ICEin intrinsic

    RalfJung committed Apr 1, 2020
    Copy the full SHA
    3911388 View commit details
  3. Auto merge of #1286 - JOE1994:windows_time, r=RalfJung

    Implement 'GetSystemTimeAsFileTime' shim for Windows
    
    Implement `GetSystemTimeAsFileTime` shim for Windows.
    
    Closes #997
    bors committed Apr 1, 2020
    Copy the full SHA
    ee967c1 View commit details
  4. rustup

    RalfJung committed Apr 1, 2020
    Copy the full SHA
    1e3800f View commit details
  5. Auto merge of #1290 - RalfJung:rustup, r=RalfJung

    Rustup
    
    Also remove ICEing `breakpoint` intrinsic shim.
    bors committed Apr 1, 2020
    Copy the full SHA
    6536f31 View commit details
  6. Copy the full SHA
    41d9070 View commit details
  7. Auto merge of #1292 - RalfJung:time, r=RalfJung

    sanity check time values a bit more
    bors committed Apr 1, 2020
    Copy the full SHA
    77a307f View commit details

Commits on Apr 2, 2020

  1. Copy the full SHA
    5130aa5 View commit details
  2. Copy the full SHA
    f599687 View commit details
  3. rustup

    RalfJung committed Apr 2, 2020
    Copy the full SHA
    165dfd7 View commit details
  4. Copy the full SHA
    5ce2466 View commit details
  5. Auto merge of #1283 - RalfJung:backtrace, r=RalfJung

    Make backtrace function names and spans match up
    
    This is the Miri side of rust-lang/rust#70590.
    Fixes #521
    bors committed Apr 2, 2020
    Copy the full SHA
    ed14328 View commit details
  6. Copy the full SHA
    0b07f6f View commit details
  7. Auto merge of #1295 - RalfJung:ci-no-incremental, r=RalfJung

    set CARGO_INCREMENTAL=0 on CI
    
    it's just a waste of time there
    bors committed Apr 2, 2020
    Copy the full SHA
    094fec3 View commit details
  8. rustup for AllocRef changes

    RalfJung committed Apr 2, 2020
    Copy the full SHA
    033eae5 View commit details
  9. Copy the full SHA
    cd132f5 View commit details
  10. Auto merge of #1296 - RalfJung:rustup, r=RalfJung

    rustup for AllocRef changes
    
    Cc rust-lang/rust#70362
    bors committed Apr 2, 2020
    Copy the full SHA
    82d46b4 View commit details
  11. Copy the full SHA
    d5beecb View commit details
  12. Auto merge of #1297 - RalfJung:win-ticks, r=RalfJung

    correct factual mistake in Windows message
    
    Also use `+` instead of `checked_add().unwrap()` (which is equivalent).
    
    Cc @JOE1994
    bors committed Apr 2, 2020
    Copy the full SHA
    4955ce3 View commit details
  13. rustup for import changes

    RalfJung committed Apr 2, 2020
    Copy the full SHA
    9f3383d View commit details
  14. Auto merge of #1299 - RalfJung:rustup, r=RalfJung

    rustup for import changes
    bors committed Apr 2, 2020
    Copy the full SHA
    147ea8f View commit details
1 change: 1 addition & 0 deletions .appveyor.yml
Original file line number Diff line number Diff line change
@@ -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
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 4 additions & 1 deletion miri
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion rust-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
9a12971da5c08f9a95d54bdaef5cd83698ed4509
537ccdf3ac44c8c7a8d36cbdbe6fb224afabb7ae
15 changes: 6 additions & 9 deletions src/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -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());
}
2 changes: 1 addition & 1 deletion src/eval.rs
Original file line number Diff line number Diff line change
@@ -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;

55 changes: 29 additions & 26 deletions src/helpers.rs
Original file line number Diff line number Diff line change
@@ -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)
})?
3 changes: 1 addition & 2 deletions src/intptrcast.rs
Original file line number Diff line number Diff line change
@@ -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};

16 changes: 5 additions & 11 deletions src/machine.rs
Original file line number Diff line number Diff line change
@@ -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)
}

7 changes: 2 additions & 5 deletions src/operator.rs
Original file line number Diff line number Diff line change
@@ -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::*;

2 changes: 1 addition & 1 deletion src/range_map.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@
use std::ops;

use rustc_middle::ty::layout::Size;
use rustc_target::abi::Size;

#[derive(Clone, Debug)]
struct Elem<T> {
10 changes: 4 additions & 6 deletions src/shims/env.rs
Original file line number Diff line number Diff line change
@@ -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
}
5 changes: 2 additions & 3 deletions src/shims/foreign_items.rs
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion src/shims/foreign_items/posix.rs
Original file line number Diff line number Diff line change
@@ -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> {
13 changes: 10 additions & 3 deletions src/shims/foreign_items/windows.rs
Original file line number Diff line number Diff line change
@@ -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'
2 changes: 1 addition & 1 deletion src/shims/fs.rs
Original file line number Diff line number Diff line change
@@ -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::*;
11 changes: 3 additions & 8 deletions src/shims/intrinsics.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,23 @@
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::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
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"
2 changes: 1 addition & 1 deletion src/shims/os_str.rs
Original file line number Diff line number Diff line change
@@ -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::*;

9 changes: 4 additions & 5 deletions src/shims/panic.rs
Original file line number Diff line number Diff line change
@@ -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)?;
32 changes: 31 additions & 1 deletion src/shims/time.rs
Original file line number Diff line number Diff line change
@@ -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();

4 changes: 2 additions & 2 deletions src/shims/tls.rs
Original file line number Diff line number Diff line change
@@ -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};

3 changes: 2 additions & 1 deletion src/stacked_borrows.rs
Original file line number Diff line number Diff line change
@@ -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::*;
11 changes: 3 additions & 8 deletions tests/compile-fail/deallocate-bad-alignment.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}
11 changes: 3 additions & 8 deletions tests/compile-fail/deallocate-bad-size.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}
13 changes: 4 additions & 9 deletions tests/compile-fail/deallocate-twice.rs
Original file line number Diff line number Diff line change
@@ -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));
}
}
4 changes: 2 additions & 2 deletions tests/compile-fail/never_transmute_void.rs
Original file line number Diff line number Diff line change
@@ -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`
}
11 changes: 3 additions & 8 deletions tests/compile-fail/reallocate-bad-size.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
13 changes: 4 additions & 9 deletions tests/compile-fail/reallocate-change-alloc.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
13 changes: 4 additions & 9 deletions tests/compile-fail/reallocate-dangling.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
17 changes: 9 additions & 8 deletions tests/run-pass/heap_allocator.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
#![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 {
for &align in &[4, 8, 16, 32] {
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);
}
34 changes: 28 additions & 6 deletions tests/run-pass/time.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}