Bubble up errors from FileDescriptor::as_file_handle
Instead of indicating incorrectly that a handle was not found, return the error from `as_file_handle` indicating the operation is not supported on the FD.
Addresses some comments in #1495
Add FileDescriptor trait to abstract fn's on File's and Stdin,Stdout,Stderr
Related issue: #1486
Instead of mapping FDs to `FileHandle`, map them to a `FileDescriptor` trait object. The goal is to eventually have both `FileHandle` as well as `Stdin`, `Stdout` and `Stderr` implement this trait so that syscalls involving FDs can handle both `File`s as well as the standard IO streams.
This PR adds the `FileDescriptor` trait and an `impl` for `FileHandle`. I'll open a separate PR for implementing the trait for the standard IO streams.
The outer InterpResult will be used to indicate that a fn is not
implemented for a struct(eg. `write` for Stdin).
The inner io::Result is just the result from the read/write/seek.
Re-organize platform-specific shims
Move platform-specific code to `shims::{posix::{linux, macos}, windows}`. Also make it private in these modules to ensure we are reasonably structured.
Add file sync shims
This PR adds shim implementations for these related file syncing functions.
* `fsync`, for POSIX targets, backed by `File::sync_all()`
* `fdatasync`, for POSIX targets, backed by `File::sync_data()`
* `fcntl` with command `F_FULLFSYNC`, for macOS targets, backed by `File::sync_all()`
* `sync_file_range`, for Linux targets, backed by `File::sync_data()`
Move cargo-miri into separate package
So far, `cargo-miri` depended on the Miri library crate. That was mostly for convenience (to avoid having to deal with workspaces), but also because until recently `cargo-miri` needed access to the ["Miri default flags"](af044209b0/src/lib.rs (L75)). But with `MIRI_BE_RUSTC` that is no longer the case, so we can remove this fake dependency. :)
@oli-obk what do you think? Also I expect the rustc bootstrap integration will need updates, hints would be appreciated. :D
Implement basic support for concurrency (Linux/macos only)
Changes (most new code is in `src/threads.rs` and `src/shims/foreign_items/posix.rs`):
1. Move the stack from `Machine` to a newly created `Thread` struct.
2. Add a `ThreadSet` struct that manages the threads.
3. Change `canonical_alloc_id` to create a unique allocation id for each thread local and thread (the responsible struct is `ThreadLocalStorage`)
4. Change the code to execute the thread local destructors immediately when a thread terminates.
5. Add the most basic round-robin scheduler.
This pull request depends on [these changes to the compiler](https://github.com/rust-lang/rust/pull/70598).
Print hex dump of alloc on reading undef bytes
Here's a small addition I made locally to the UB diagnostics, in case you're interested in it. This PR calls `dump_alloc()` on the relevant allocation if Miri fails on UB due to reading undefined bytes. This came in handy when diagnosing such an issue in a large program using unsafe Rust, in part because it wasn't deterministic enough to use `-Zmiri-track-alloc-id=`. If you'd like to put this behind another -Z flag, let me know.
Handle std::sync::atomic::spin_loop_hint()
This PR adds support for `std::sync::atomic::spin_loop_hint()` by implementing the `llvm.x86.sse2.pause` intrinsic when the target is x86-based. It appears this is the first LLVM intrinsic in foreign_items, so I added a couple match blocks to handle it or fall through to the different OS-specific methods. I added a basic smoke test to `tests/run-pass/sync.rs`. I came across this by way of `crossbeam::utils::Backoff::spin()`, FWIW.
implement float_to_int_unchecked
@hanna-kruppe would be great if you could have a look at this.
`float.rs` tests legal casts. `test_cast` checks that both `as` casts and unchecked casts work (i.e., these are not saturating). The `compile-fail` tests should ensure that illegal casts via the intrinsic are detected as such.
Fixes https://github.com/rust-lang/miri/issues/1264
Implement `mach_timebase_info` for macOS
Since we return nanoseceonds instead of ticks from `mach_absolute_time`, we don't need to scale the absolute time
Fixes#1288
add empty line before backtrace, to separate it from help text
I think this improves how things look, and makes it easier to see the help text (it currently kind of drowns next to the backtrace).
Before:
```
error: unsupported operation: Miri does not support threading
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
|
68 | let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Miri does not support threading
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
= note: inside `std::sys::unix:🧵:Thread::new` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
= note: inside `std:🧵:Builder::spawn_unchecked::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:492:26
= note: inside `std:🧵:Builder::spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:386:18
= note: inside `std:🧵:spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:619:5
note: inside `main` at tests/compile-fail/thread-spawn.rs:6:5
--> tests/compile-fail/thread-spawn.rs:6:5
|
6 | thread::spawn(|| {});
| ^^^^^^^^^^^^^^^^^^^^
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:34
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:73
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1:6030 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys_common/backtrace.rs:130:5
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:13
= note: inside `std::panicking::try::do_call::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:331:40
= note: inside `std::panicking::try::<i32, [closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:274:15
= note: inside `std::panic::catch_unwind::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panic.rs:394:14
= note: inside `std::rt::lang_start_internal` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:51:25
= note: inside `std::rt::lang_start::<()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:5
```
After:
```
error: unsupported operation: Miri does not support threading
--> /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
|
68 | let ret = libc::pthread_create(&mut native, &attr, thread_start, &*p as *const _ as *mut _);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Miri does not support threading
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support
= note: inside `std::sys::unix:🧵:Thread::new` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys/unix/thread.rs:68:19
= note: inside `std:🧵:Builder::spawn_unchecked::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:492:26
= note: inside `std:🧵:Builder::spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:386:18
= note: inside `std:🧵:spawn::<[closure@tests/compile-fail/thread-spawn.rs:6:19: 6:24], ()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/thread/mod.rs:619:5
note: inside `main` at tests/compile-fail/thread-spawn.rs:6:5
--> tests/compile-fail/thread-spawn.rs:6:5
|
6 | thread::spawn(|| {});
| ^^^^^^^^^^^^^^^^^^^^
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:34
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:73
= note: inside `std::sys_common::backtrace::__rust_begin_short_backtrace::<[closure@DefId(1:6030 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]::{{closure}}[0]) 0:&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/sys_common/backtrace.rs:130:5
= note: inside closure at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:52:13
= note: inside `std::panicking::try::do_call::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:331:40
= note: inside `std::panicking::try::<i32, [closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe]>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panicking.rs:274:15
= note: inside `std::panic::catch_unwind::<[closure@DefId(1:6029 ~ std[2f86]::rt[0]::lang_start_internal[0]::{{closure}}[0]) 0:&&dyn std::ops::Fn() -> i32 + std::marker::Sync + std::panic::RefUnwindSafe], i32>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/panic.rs:394:14
= note: inside `std::rt::lang_start_internal` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:51:25
= note: inside `std::rt::lang_start::<()>` at /home/r/.rustup/toolchains/miri/lib/rustlib/src/rust/src/libstd/rt.rs:67:5
```
What do you think?
Add shims for RwLock::try_read/RwLock::try_write
This implements proper locking so that we can check for reentrancy and implement the `try_*` methods.
Fixes https://github.com/rust-lang/miri/issues/781
Rust bootstrap sysroot now has src in the same place as rust-src
So we can remove a special hack. I checked this locally to confirm it works.
Cc https://github.com/rust-lang/rust/pull/70642 @eddyb
Add support for 'std::time::Instant' in Windows
Add support for creating `std::time::Instant` in Windows
Includes shims for `QueryPerformanceCounter` & `QueryPerformanceFrequency` in Windows, which are both called in Windows when `std::time::Instant` is created.
Windows docs page ["Acquiring high-resolution time stamps"](https://docs.microsoft.com/en-us/windows/win32/sysinfo/acquiring-high-resolution-time-stamps) was helpful in learning how `QueryPerformanceCounter` & `QueryPerformanceFrequency` work.
closes#1291
Add support for OpenOptions::create_new()/O_EXCL
This PR extends the POSIX shim for `open` to support the `O_EXCL` flag, when it is used alongside `O_CREAT`, and exercises it by testing `OpenOptions::create_new`.