From ac9368ab1eece4419e9bee4426c6389f8ae28450 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Mon, 25 Dec 2023 17:09:14 -0800 Subject: [PATCH 01/10] have windows tests use windows-sys --- src/tools/miri/test_dependencies/Cargo.lock | 179 ++++++++++++------ src/tools/miri/test_dependencies/Cargo.toml | 3 + .../concurrency/windows_join_detached.rs | 8 +- .../concurrency/windows_join_detached.stderr | 0 .../concurrency/windows_join_main.rs | 11 +- .../concurrency/windows_join_main.stderr | 4 +- .../concurrency/windows_join_self.rs | 10 +- .../concurrency/windows_join_self.stderr | 2 +- .../concurrency/windows_condvar_shared.rs | 51 ++--- .../concurrency/windows_condvar_shared.stdout | 0 .../concurrency/windows_detach_terminated.rs | 8 +- .../concurrency/windows_init_once.rs | 81 ++++---- .../concurrency/windows_init_once.stdout | 0 .../concurrency/windows_join_multiple.rs | 11 +- 14 files changed, 212 insertions(+), 156 deletions(-) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/windows_join_detached.rs (62%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/windows_join_detached.stderr (100%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/windows_join_main.rs (70%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/windows_join_main.stderr (87%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/windows_join_self.rs (57%) rename src/tools/miri/tests/{fail => fail-dep}/concurrency/windows_join_self.stderr (96%) rename src/tools/miri/tests/{pass => pass-dep}/concurrency/windows_condvar_shared.rs (83%) rename src/tools/miri/tests/{pass => pass-dep}/concurrency/windows_condvar_shared.stdout (100%) rename src/tools/miri/tests/{pass => pass-dep}/concurrency/windows_detach_terminated.rs (65%) rename src/tools/miri/tests/{pass => pass-dep}/concurrency/windows_init_once.rs (65%) rename src/tools/miri/tests/{pass => pass-dep}/concurrency/windows_init_once.stdout (100%) rename src/tools/miri/tests/{pass => pass-dep}/concurrency/windows_join_multiple.rs (77%) diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 8d18d8535d8f5..4700b519495fe 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" dependencies = [ "cfg-if", "js-sys", @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "hermit-abi" @@ -109,24 +109,24 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.148" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -155,13 +155,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -169,12 +169,13 @@ name = "miri-test-deps" version = "0.1.0" dependencies = [ "getrandom 0.1.16", - "getrandom 0.2.10", + "getrandom 0.2.11", "libc", "num_cpus", "page_size", "rand", "tokio", + "windows-sys 0.52.0", ] [[package]] @@ -189,18 +190,18 @@ dependencies = [ [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "page_size" @@ -224,15 +225,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -249,9 +250,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" dependencies = [ "unicode-ident", ] @@ -292,14 +293,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.10", + "getrandom 0.2.11", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags", ] @@ -327,25 +328,25 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "syn" -version = "2.0.37" +version = "2.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" dependencies = [ "proc-macro2", "quote", @@ -354,9 +355,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.32.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", @@ -368,14 +369,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", @@ -402,9 +403,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -412,9 +413,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" dependencies = [ "bumpalo", "log", @@ -427,9 +428,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -437,9 +438,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", @@ -450,9 +451,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "winapi" @@ -482,7 +483,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -491,13 +501,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -506,38 +531,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index d54560608dc1e..f7d385f589097 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -20,4 +20,7 @@ rand = { version = "0.8", features = ["small_rng"] } page_size = "0.6" tokio = { version = "1.24", features = ["full"] } +[target.'cfg(windows)'.dependencies] +windows-sys = { version = "0.52", features = [ "Win32_Foundation", "Win32_System_Threading" ] } + [workspace] diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs similarity index 62% rename from src/tools/miri/tests/fail/concurrency/windows_join_detached.rs rename to src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs index b68a07797f8bd..8befd3c442a08 100644 --- a/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs @@ -3,18 +3,16 @@ // Joining a detached thread is undefined behavior. -use std::os::windows::io::{AsRawHandle, RawHandle}; +use std::os::windows::io::AsRawHandle; use std::thread; -extern "system" { - fn CloseHandle(handle: RawHandle) -> u32; -} +use windows_sys::Win32::Foundation::CloseHandle; fn main() { let thread = thread::spawn(|| ()); unsafe { - assert_ne!(CloseHandle(thread.as_raw_handle()), 0); + assert_ne!(CloseHandle(thread.as_raw_handle() as _), 0); } thread.join().unwrap(); diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr similarity index 100% rename from src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr rename to src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_main.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs similarity index 70% rename from src/tools/miri/tests/fail/concurrency/windows_join_main.rs rename to src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs index cde6d19ef25bb..910e06222ee76 100644 --- a/src/tools/miri/tests/fail/concurrency/windows_join_main.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs @@ -6,21 +6,18 @@ use std::thread; -extern "system" { - fn WaitForSingleObject(handle: isize, timeout: u32) -> u32; -} - -const INFINITE: u32 = u32::MAX; +use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0}; +use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE}; // XXX HACK: This is how miri represents the handle for thread 0. // This value can be "legitimately" obtained by using `GetCurrentThread` with `DuplicateHandle` // but miri does not implement `DuplicateHandle` yet. -const MAIN_THREAD: isize = (2i32 << 30) as isize; +const MAIN_THREAD: HANDLE = (2i32 << 30) as HANDLE; fn main() { thread::spawn(|| { unsafe { - assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), 0); //~ ERROR: deadlock: the evaluated program deadlocked + assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0); //~ ERROR: deadlock: the evaluated program deadlocked } }) .join() diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr similarity index 87% rename from src/tools/miri/tests/fail/concurrency/windows_join_main.stderr rename to src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr index 94fe95a0bdfab..cb51c7e0bd985 100644 --- a/src/tools/miri/tests/fail/concurrency/windows_join_main.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr @@ -1,8 +1,8 @@ error: deadlock: the evaluated program deadlocked --> $DIR/windows_join_main.rs:LL:CC | -LL | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), 0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked +LL | assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked | = note: inside closure at RUSTLIB/core/src/macros/mod.rs:LL:CC = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_self.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.rs similarity index 57% rename from src/tools/miri/tests/fail/concurrency/windows_join_self.rs rename to src/tools/miri/tests/fail-dep/concurrency/windows_join_self.rs index d9bbf66a7dca5..a7c8faf5a98ba 100644 --- a/src/tools/miri/tests/fail/concurrency/windows_join_self.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.rs @@ -6,18 +6,14 @@ use std::thread; -extern "system" { - fn GetCurrentThread() -> usize; - fn WaitForSingleObject(handle: usize, timeout: u32) -> u32; -} - -const INFINITE: u32 = u32::MAX; +use windows_sys::Win32::Foundation::WAIT_OBJECT_0; +use windows_sys::Win32::System::Threading::{GetCurrentThread, WaitForSingleObject, INFINITE}; fn main() { thread::spawn(|| { unsafe { let native = GetCurrentThread(); - assert_eq!(WaitForSingleObject(native, INFINITE), 0); //~ ERROR: deadlock: the evaluated program deadlocked + assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0); //~ ERROR: deadlock: the evaluated program deadlocked } }) .join() diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_self.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr similarity index 96% rename from src/tools/miri/tests/fail/concurrency/windows_join_self.stderr rename to src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr index 0d2a22677c7ae..8b76e12421552 100644 --- a/src/tools/miri/tests/fail/concurrency/windows_join_self.stderr +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr @@ -1,7 +1,7 @@ error: deadlock: the evaluated program deadlocked --> $DIR/windows_join_self.rs:LL:CC | -LL | assert_eq!(WaitForSingleObject(native, INFINITE), 0); +LL | assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0); | ^ the evaluated program deadlocked | = note: inside closure at $DIR/windows_join_self.rs:LL:CC diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs similarity index 83% rename from src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs rename to src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs index 3b27af9094cc5..eb32f7b66b2fb 100644 --- a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs @@ -2,42 +2,29 @@ // We are making scheduler assumptions here. //@compile-flags: -Zmiri-preemption-rate=0 -use std::ffi::c_void; -use std::ptr::null_mut; +use std::mem::MaybeUninit; use std::thread; +use windows_sys::Win32::System::Threading::{ + AcquireSRWLockExclusive, AcquireSRWLockShared, ReleaseSRWLockExclusive, ReleaseSRWLockShared, + SleepConditionVariableSRW, WakeAllConditionVariable, CONDITION_VARIABLE_LOCKMODE_SHARED, + INFINITE, +}; + #[derive(Copy, Clone)] struct SendPtr(*mut T); unsafe impl Send for SendPtr {} -extern "system" { - fn SleepConditionVariableSRW( - condvar: *mut *mut c_void, - lock: *mut *mut c_void, - timeout: u32, - flags: u32, - ) -> i32; - fn WakeAllConditionVariable(condvar: *mut *mut c_void); - - fn AcquireSRWLockExclusive(lock: *mut *mut c_void); - fn AcquireSRWLockShared(lock: *mut *mut c_void); - fn ReleaseSRWLockExclusive(lock: *mut *mut c_void); - fn ReleaseSRWLockShared(lock: *mut *mut c_void); -} - -const CONDITION_VARIABLE_LOCKMODE_SHARED: u32 = 1; -const INFINITE: u32 = u32::MAX; - /// threads should be able to reacquire the lock while it is locked by multiple other threads in shared mode fn all_shared() { println!("all_shared"); - let mut lock = null_mut(); - let mut condvar = null_mut(); + let mut lock = MaybeUninit::zeroed(); + let mut condvar = MaybeUninit::zeroed(); - let lock_ptr = SendPtr(&mut lock); - let condvar_ptr = SendPtr(&mut condvar); + let lock_ptr = SendPtr(lock.as_mut_ptr()); + let condvar_ptr = SendPtr(condvar.as_mut_ptr()); let mut handles = Vec::with_capacity(10); @@ -105,11 +92,11 @@ fn all_shared() { fn shared_sleep_and_exclusive_lock() { println!("shared_sleep_and_exclusive_lock"); - let mut lock = null_mut(); - let mut condvar = null_mut(); + let mut lock = MaybeUninit::zeroed(); + let mut condvar = MaybeUninit::zeroed(); - let lock_ptr = SendPtr(&mut lock); - let condvar_ptr = SendPtr(&mut condvar); + let lock_ptr = SendPtr(lock.as_mut_ptr()); + let condvar_ptr = SendPtr(condvar.as_mut_ptr()); let mut waiters = Vec::with_capacity(5); for i in 0..5 { @@ -166,11 +153,11 @@ fn shared_sleep_and_exclusive_lock() { fn exclusive_sleep_and_shared_lock() { println!("exclusive_sleep_and_shared_lock"); - let mut lock = null_mut(); - let mut condvar = null_mut(); + let mut lock = MaybeUninit::zeroed(); + let mut condvar = MaybeUninit::zeroed(); - let lock_ptr = SendPtr(&mut lock); - let condvar_ptr = SendPtr(&mut condvar); + let lock_ptr = SendPtr(lock.as_mut_ptr()); + let condvar_ptr = SendPtr(condvar.as_mut_ptr()); let mut handles = Vec::with_capacity(10); for i in 0..5 { diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.stdout similarity index 100% rename from src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout rename to src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.stdout diff --git a/src/tools/miri/tests/pass/concurrency/windows_detach_terminated.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs similarity index 65% rename from src/tools/miri/tests/pass/concurrency/windows_detach_terminated.rs rename to src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs index 91088ce6aef9b..a11799815e0f4 100644 --- a/src/tools/miri/tests/pass/concurrency/windows_detach_terminated.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs @@ -5,17 +5,15 @@ use std::os::windows::io::IntoRawHandle; use std::thread; -extern "system" { - fn CloseHandle(handle: usize) -> i32; -} +use windows_sys::Win32::Foundation::CloseHandle; fn main() { - let thread = thread::spawn(|| {}).into_raw_handle() as usize; + let thread = thread::spawn(|| {}).into_raw_handle(); // this yield ensures that `thread` is terminated by this point thread::yield_now(); unsafe { - assert_ne!(CloseHandle(thread), 0); + assert_ne!(CloseHandle(thread as _), 0); } } diff --git a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs similarity index 65% rename from src/tools/miri/tests/pass/concurrency/windows_init_once.rs rename to src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs index b2412f7dbb0e6..57d2a5657a3eb 100644 --- a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs @@ -2,68 +2,75 @@ // We are making scheduler assumptions here. //@compile-flags: -Zmiri-preemption-rate=0 -use std::ffi::c_void; +use std::mem::MaybeUninit; use std::ptr::null_mut; use std::thread; +use windows_sys::Win32::Foundation::{FALSE, TRUE}; +use windows_sys::Win32::System::Threading::{ + InitOnceBeginInitialize, InitOnceComplete, INIT_ONCE_INIT_FAILED, +}; + #[derive(Copy, Clone)] struct SendPtr(*mut T); unsafe impl Send for SendPtr {} -extern "system" { - fn InitOnceBeginInitialize( - init: *mut *mut c_void, - flags: u32, - pending: *mut i32, - context: *mut c_void, - ) -> i32; - - fn InitOnceComplete(init: *mut *mut c_void, flags: u32, context: *mut c_void) -> i32; -} - -const TRUE: i32 = 1; -const FALSE: i32 = 0; - -const INIT_ONCE_INIT_FAILED: u32 = 4; - fn single_thread() { - let mut init_once = null_mut(); + let mut init_once = MaybeUninit::zeroed(); let mut pending = 0; unsafe { - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, TRUE); - assert_eq!(InitOnceComplete(&mut init_once, 0, null_mut()), TRUE); + assert_eq!(InitOnceComplete(init_once.as_mut_ptr(), 0, null_mut()), TRUE); - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, FALSE); } - let mut init_once = null_mut(); + let mut init_once = MaybeUninit::zeroed(); unsafe { - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, TRUE); - assert_eq!(InitOnceComplete(&mut init_once, INIT_ONCE_INIT_FAILED, null_mut()), TRUE); + assert_eq!( + InitOnceComplete(init_once.as_mut_ptr(), INIT_ONCE_INIT_FAILED, null_mut()), + TRUE + ); - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, TRUE); } } fn block_until_complete() { - let mut init_once = null_mut(); + let mut init_once = MaybeUninit::zeroed(); let mut pending = 0; unsafe { - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, TRUE); } - let init_once_ptr = SendPtr(&mut init_once); + let init_once_ptr = SendPtr(init_once.as_mut_ptr()); let waiter = move || unsafe { let init_once_ptr = init_once_ptr; // avoid field capture @@ -92,15 +99,18 @@ fn block_until_complete() { } fn retry_on_fail() { - let mut init_once = null_mut(); + let mut init_once = MaybeUninit::zeroed(); let mut pending = 0; unsafe { - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, TRUE); } - let init_once_ptr = SendPtr(&mut init_once); + let init_once_ptr = SendPtr(init_once.as_mut_ptr()); let waiter = move || unsafe { let init_once_ptr = init_once_ptr; // avoid field capture @@ -134,15 +144,18 @@ fn retry_on_fail() { } fn no_data_race_after_complete() { - let mut init_once = null_mut(); + let mut init_once = MaybeUninit::zeroed(); let mut pending = 0; unsafe { - assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); + assert_eq!( + InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), + TRUE + ); assert_eq!(pending, TRUE); } - let init_once_ptr = SendPtr(&mut init_once); + let init_once_ptr = SendPtr(init_once.as_mut_ptr()); let mut place = 0; let place_ptr = SendPtr(&mut place); diff --git a/src/tools/miri/tests/pass/concurrency/windows_init_once.stdout b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.stdout similarity index 100% rename from src/tools/miri/tests/pass/concurrency/windows_init_once.stdout rename to src/tools/miri/tests/pass-dep/concurrency/windows_init_once.stdout diff --git a/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs similarity index 77% rename from src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs rename to src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs index 5da5497f9829f..fb0fbc307fb9b 100644 --- a/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs @@ -6,11 +6,8 @@ use std::os::windows::io::IntoRawHandle; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; -extern "system" { - fn WaitForSingleObject(handle: usize, timeout: u32) -> u32; -} - -const INFINITE: u32 = u32::MAX; +use windows_sys::Win32::Foundation::WAIT_OBJECT_0; +use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE}; fn main() { static FLAG: AtomicBool = AtomicBool::new(false); @@ -20,10 +17,10 @@ fn main() { thread::yield_now(); } }) - .into_raw_handle() as usize; + .into_raw_handle() as _; let waiter = move || unsafe { - assert_eq!(WaitForSingleObject(blocker, INFINITE), 0); + assert_eq!(WaitForSingleObject(blocker, INFINITE), WAIT_OBJECT_0); }; let waiter1 = thread::spawn(waiter); From dae48ea4bb28857153bf1705694022e7e0b411ce Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 27 Dec 2023 20:31:28 +0100 Subject: [PATCH 02/10] fast_math: detect non-finite results --- src/tools/miri/src/shims/intrinsics/mod.rs | 6 +++++- .../tests/fail/{ => intrinsics}/fast_math_both.rs | 0 .../fail/{ => intrinsics}/fast_math_both.stderr | 0 .../fail/{ => intrinsics}/fast_math_first.rs | 0 .../fail/{ => intrinsics}/fast_math_first.stderr | 0 .../tests/fail/intrinsics/fast_math_result.rs | 7 +++++++ .../tests/fail/intrinsics/fast_math_result.stderr | 15 +++++++++++++++ .../fail/{ => intrinsics}/fast_math_second.rs | 0 .../fail/{ => intrinsics}/fast_math_second.stderr | 0 9 files changed, 27 insertions(+), 1 deletion(-) rename src/tools/miri/tests/fail/{ => intrinsics}/fast_math_both.rs (100%) rename src/tools/miri/tests/fail/{ => intrinsics}/fast_math_both.stderr (100%) rename src/tools/miri/tests/fail/{ => intrinsics}/fast_math_first.rs (100%) rename src/tools/miri/tests/fail/{ => intrinsics}/fast_math_first.stderr (100%) create mode 100644 src/tools/miri/tests/fail/intrinsics/fast_math_result.rs create mode 100644 src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr rename src/tools/miri/tests/fail/{ => intrinsics}/fast_math_second.rs (100%) rename src/tools/miri/tests/fail/{ => intrinsics}/fast_math_second.stderr (100%) diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 66918db995d03..625ae3ef39e5e 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -268,7 +268,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ), _ => {} } - this.binop_ignore_overflow(op, &a, &b, dest)?; + let res = this.wrapping_binary_op(op, &a, &b)?; + if !float_finite(&res)? { + throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result"); + } + this.write_immediate(*res, dest)?; } #[rustfmt::skip] diff --git a/src/tools/miri/tests/fail/fast_math_both.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_both.rs similarity index 100% rename from src/tools/miri/tests/fail/fast_math_both.rs rename to src/tools/miri/tests/fail/intrinsics/fast_math_both.rs diff --git a/src/tools/miri/tests/fail/fast_math_both.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_both.stderr similarity index 100% rename from src/tools/miri/tests/fail/fast_math_both.stderr rename to src/tools/miri/tests/fail/intrinsics/fast_math_both.stderr diff --git a/src/tools/miri/tests/fail/fast_math_first.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_first.rs similarity index 100% rename from src/tools/miri/tests/fail/fast_math_first.rs rename to src/tools/miri/tests/fail/intrinsics/fast_math_first.rs diff --git a/src/tools/miri/tests/fail/fast_math_first.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_first.stderr similarity index 100% rename from src/tools/miri/tests/fail/fast_math_first.stderr rename to src/tools/miri/tests/fail/intrinsics/fast_math_first.stderr diff --git a/src/tools/miri/tests/fail/intrinsics/fast_math_result.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_result.rs new file mode 100644 index 0000000000000..4a143da057556 --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/fast_math_result.rs @@ -0,0 +1,7 @@ +#![feature(core_intrinsics)] + +fn main() { + unsafe { + let _x: f32 = core::intrinsics::fdiv_fast(1.0, 0.0); //~ ERROR: `fdiv_fast` intrinsic produced non-finite value as result + } +} diff --git a/src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr new file mode 100644 index 0000000000000..5b24d2250266d --- /dev/null +++ b/src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: `fdiv_fast` intrinsic produced non-finite value as result + --> $DIR/fast_math_result.rs:LL:CC + | +LL | let _x: f32 = core::intrinsics::fdiv_fast(1.0, 0.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fdiv_fast` intrinsic produced non-finite value as result + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/fast_math_result.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/fast_math_second.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_second.rs similarity index 100% rename from src/tools/miri/tests/fail/fast_math_second.rs rename to src/tools/miri/tests/fail/intrinsics/fast_math_second.rs diff --git a/src/tools/miri/tests/fail/fast_math_second.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_second.stderr similarity index 100% rename from src/tools/miri/tests/fail/fast_math_second.stderr rename to src/tools/miri/tests/fail/intrinsics/fast_math_second.stderr From cf2ef7dc79e0b53129e3d1f996a7126107253cd1 Mon Sep 17 00:00:00 2001 From: Pointerbender Date: Thu, 28 Dec 2023 08:18:50 +1100 Subject: [PATCH 03/10] Support for tempfile crate on UNIX hosts Co-authored-by: Jefffrey <22608443+Jefffrey@users.noreply.github.com> Co-authored-by: Ralf Jung --- src/tools/miri/src/shims/unix/fs.rs | 17 ++- src/tools/miri/test_dependencies/Cargo.lock | 158 ++++++++++++++++++-- src/tools/miri/test_dependencies/Cargo.toml | 1 + src/tools/miri/tests/pass-dep/tempfile.rs | 21 +++ 4 files changed, 181 insertions(+), 16 deletions(-) create mode 100644 src/tools/miri/tests/pass-dep/tempfile.rs diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 1402f07dd38dc..99d8a3a2c91f4 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -559,8 +559,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { ); }; - if mode != 0o666 { - throw_unsup_format!("non-default mode 0o{:o} is not supported", mode); + #[cfg(unix)] + { + // Support all modes on UNIX host + use std::os::unix::fs::OpenOptionsExt; + options.mode(mode); + } + #[cfg(not(unix))] + { + // Only support default mode for non-UNIX (i.e. Windows) host + if mode != 0o666 { + throw_unsup_format!( + "non-default mode 0o{:o} is not supported on non-Unix hosts", + mode + ); + } } mirror |= o_creat; diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 8d18d8535d8f5..3d9cb902da0f1 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -44,6 +44,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "bumpalo" version = "3.14.0" @@ -71,6 +77,22 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "fastrand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" + [[package]] name = "getrandom" version = "0.1.16" @@ -122,6 +144,12 @@ version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +[[package]] +name = "linux-raw-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" + [[package]] name = "lock_api" version = "0.4.10" @@ -161,7 +189,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -174,6 +202,7 @@ dependencies = [ "num_cpus", "page_size", "rand", + "tempfile", "tokio", ] @@ -230,9 +259,9 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.3.5", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -301,7 +330,16 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", ] [[package]] @@ -310,6 +348,19 @@ version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustix" +version = "0.38.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3" +dependencies = [ + "bitflags 2.4.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -338,7 +389,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -352,6 +403,19 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.4.1", + "rustix", + "windows-sys 0.48.0", +] + [[package]] name = "tokio" version = "1.32.0" @@ -368,7 +432,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -482,7 +546,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -491,13 +564,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -506,38 +594,80 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml index d54560608dc1e..2e836a8acd17c 100644 --- a/src/tools/miri/test_dependencies/Cargo.toml +++ b/src/tools/miri/test_dependencies/Cargo.toml @@ -11,6 +11,7 @@ edition = "2021" # all dependencies (and their transitive ones) listed here can be used in `tests/`. libc = "0.2" num_cpus = "1.10.1" +tempfile = "3" getrandom_01 = { package = "getrandom", version = "0.1" } getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] } diff --git a/src/tools/miri/tests/pass-dep/tempfile.rs b/src/tools/miri/tests/pass-dep/tempfile.rs new file mode 100644 index 0000000000000..c4583ca3f47a4 --- /dev/null +++ b/src/tools/miri/tests/pass-dep/tempfile.rs @@ -0,0 +1,21 @@ +//@ignore-target-windows: File handling is not implemented yet +//@ignore-host-windows: Only supported for UNIX hosts +//@compile-flags: -Zmiri-disable-isolation + +#[path = "../utils/mod.rs"] +mod utils; + +/// Test that the [`tempfile`] crate is compatible with miri for UNIX hosts and targets +fn main() { + test_tempfile(); + test_tempfile_in(); +} + +fn test_tempfile() { + tempfile::tempfile().unwrap(); +} + +fn test_tempfile_in() { + let dir_path = utils::tmp(); + tempfile::tempfile_in(dir_path).unwrap(); +} From 86198a15d7f67ad61a7988d881e9af68a0bbf361 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Dec 2023 08:41:51 +0100 Subject: [PATCH 04/10] make float intrinsics return non-deterministic NaN --- src/tools/miri/src/helpers.rs | 45 ++++++ src/tools/miri/src/operator.rs | 4 + src/tools/miri/src/shims/intrinsics/mod.rs | 166 +++++++++++---------- src/tools/miri/tests/pass/float_nan.rs | 98 ++++++++++++ 4 files changed, 238 insertions(+), 75 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index d2fd51b099ad7..98f646da6b69f 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -6,6 +6,7 @@ use std::time::Duration; use log::trace; use rustc_apfloat::ieee::{Double, Single}; +use rustc_apfloat::Float; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_index::IndexVec; @@ -117,6 +118,50 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option) } } +/// Convert a softfloat type to its corresponding hostfloat type. +pub trait ToHost { + type HostFloat; + fn to_host(self) -> Self::HostFloat; +} + +/// Convert a hostfloat type to its corresponding softfloat type. +pub trait ToSoft { + type SoftFloat; + fn to_soft(self) -> Self::SoftFloat; +} + +impl ToHost for rustc_apfloat::ieee::Double { + type HostFloat = f64; + + fn to_host(self) -> Self::HostFloat { + f64::from_bits(self.to_bits().try_into().unwrap()) + } +} + +impl ToSoft for f64 { + type SoftFloat = rustc_apfloat::ieee::Double; + + fn to_soft(self) -> Self::SoftFloat { + Float::from_bits(self.to_bits().into()) + } +} + +impl ToHost for rustc_apfloat::ieee::Single { + type HostFloat = f32; + + fn to_host(self) -> Self::HostFloat { + f32::from_bits(self.to_bits().try_into().unwrap()) + } +} + +impl ToSoft for f32 { + type SoftFloat = rustc_apfloat::ieee::Single; + + fn to_soft(self) -> Self::SoftFloat { + Float::from_bits(self.to_bits().into()) + } +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Checks if the given crate/module exists. diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs index e5a437f95f0ea..140764446969a 100644 --- a/src/tools/miri/src/operator.rs +++ b/src/tools/miri/src/operator.rs @@ -118,4 +118,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { nan } } + + fn adjust_nan, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 { + if f.is_nan() { self.generate_nan(inputs) } else { f } + } } diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 625ae3ef39e5e..cc81ef6e6c916 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -15,7 +15,7 @@ use rustc_target::abi::Size; use crate::*; use atomic::EvalContextExt as _; -use helpers::check_arg_count; +use helpers::{check_arg_count, ToHost, ToSoft}; use simd::EvalContextExt as _; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -146,12 +146,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f32()?; // Can be implemented in soft-floats. + // This is a "bitwise" operation, so there's no NaN non-determinism. this.write_scalar(Scalar::from_f32(f.abs()), dest)?; } "fabsf64" => { let [f] = check_arg_count(args)?; let f = this.read_scalar(f)?.to_f64()?; // Can be implemented in soft-floats. + // This is a "bitwise" operation, so there's no NaN non-determinism. this.write_scalar(Scalar::from_f64(f.abs()), dest)?; } #[rustfmt::skip] @@ -170,25 +172,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "rintf32" => { let [f] = check_arg_count(args)?; + let f = this.read_scalar(f)?.to_f32()?; // FIXME: Using host floats. - let f = f32::from_bits(this.read_scalar(f)?.to_u32()?); - let f = match intrinsic_name { - "sinf32" => f.sin(), - "cosf32" => f.cos(), - "sqrtf32" => f.sqrt(), - "expf32" => f.exp(), - "exp2f32" => f.exp2(), - "logf32" => f.ln(), - "log10f32" => f.log10(), - "log2f32" => f.log2(), - "floorf32" => f.floor(), - "ceilf32" => f.ceil(), - "truncf32" => f.trunc(), - "roundf32" => f.round(), - "rintf32" => f.round_ties_even(), + let f_host = f.to_host(); + let res = match intrinsic_name { + "sinf32" => f_host.sin(), + "cosf32" => f_host.cos(), + "sqrtf32" => f_host.sqrt(), + "expf32" => f_host.exp(), + "exp2f32" => f_host.exp2(), + "logf32" => f_host.ln(), + "log10f32" => f_host.log10(), + "log2f32" => f_host.log2(), + "floorf32" => f_host.floor(), + "ceilf32" => f_host.ceil(), + "truncf32" => f_host.trunc(), + "roundf32" => f_host.round(), + "rintf32" => f_host.round_ties_even(), _ => bug!(), }; - this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?; + let res = res.to_soft(); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; } #[rustfmt::skip] @@ -207,25 +212,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "rintf64" => { let [f] = check_arg_count(args)?; + let f = this.read_scalar(f)?.to_f64()?; // FIXME: Using host floats. - let f = f64::from_bits(this.read_scalar(f)?.to_u64()?); - let f = match intrinsic_name { - "sinf64" => f.sin(), - "cosf64" => f.cos(), - "sqrtf64" => f.sqrt(), - "expf64" => f.exp(), - "exp2f64" => f.exp2(), - "logf64" => f.ln(), - "log10f64" => f.log10(), - "log2f64" => f.log2(), - "floorf64" => f.floor(), - "ceilf64" => f.ceil(), - "truncf64" => f.trunc(), - "roundf64" => f.round(), - "rintf64" => f.round_ties_even(), + let f_host = f.to_host(); + let res = match intrinsic_name { + "sinf64" => f_host.sin(), + "cosf64" => f_host.cos(), + "sqrtf64" => f_host.sqrt(), + "expf64" => f_host.exp(), + "exp2f64" => f_host.exp2(), + "logf64" => f_host.ln(), + "log10f64" => f_host.log10(), + "log2f64" => f_host.log2(), + "floorf64" => f_host.floor(), + "ceilf64" => f_host.ceil(), + "truncf64" => f_host.trunc(), + "roundf64" => f_host.round(), + "rintf64" => f_host.round_ties_even(), _ => bug!(), }; - this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?; + let res = res.to_soft(); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; } #[rustfmt::skip] @@ -272,6 +280,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if !float_finite(&res)? { throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result"); } + // This cannot be a NaN so we also don't have to apply any non-determinism. + // (Also, `wrapping_binary_op` already called `generate_nan` if needed.) this.write_immediate(*res, dest)?; } @@ -284,9 +294,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let a = this.read_scalar(a)?.to_f32()?; let b = this.read_scalar(b)?.to_f32()?; let res = match intrinsic_name { - "minnumf32" => a.min(b), - "maxnumf32" => a.max(b), - "copysignf32" => a.copy_sign(b), + "minnumf32" => this.adjust_nan(a.min(b), &[a, b]), + "maxnumf32" => this.adjust_nan(a.max(b), &[a, b]), + "copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments _ => bug!(), }; this.write_scalar(Scalar::from_f32(res), dest)?; @@ -301,68 +311,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let a = this.read_scalar(a)?.to_f64()?; let b = this.read_scalar(b)?.to_f64()?; let res = match intrinsic_name { - "minnumf64" => a.min(b), - "maxnumf64" => a.max(b), - "copysignf64" => a.copy_sign(b), + "minnumf64" => this.adjust_nan(a.min(b), &[a, b]), + "maxnumf64" => this.adjust_nan(a.max(b), &[a, b]), + "copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments _ => bug!(), }; this.write_scalar(Scalar::from_f64(res), dest)?; } - "powf32" => { - let [f, f2] = check_arg_count(args)?; - // FIXME: Using host floats. - let f = f32::from_bits(this.read_scalar(f)?.to_u32()?); - let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?); - let res = f.powf(f2); - this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; - } - - "powf64" => { - let [f, f2] = check_arg_count(args)?; - // FIXME: Using host floats. - let f = f64::from_bits(this.read_scalar(f)?.to_u64()?); - let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?); - let res = f.powf(f2); - this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; - } - "fmaf32" => { let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f32()?; + let b = this.read_scalar(b)?.to_f32()?; + let c = this.read_scalar(c)?.to_f32()?; // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 - let a = f32::from_bits(this.read_scalar(a)?.to_u32()?); - let b = f32::from_bits(this.read_scalar(b)?.to_u32()?); - let c = f32::from_bits(this.read_scalar(c)?.to_u32()?); - let res = a.mul_add(b, c); - this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; + let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; } "fmaf64" => { let [a, b, c] = check_arg_count(args)?; + let a = this.read_scalar(a)?.to_f64()?; + let b = this.read_scalar(b)?.to_f64()?; + let c = this.read_scalar(c)?.to_f64()?; // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11 - let a = f64::from_bits(this.read_scalar(a)?.to_u64()?); - let b = f64::from_bits(this.read_scalar(b)?.to_u64()?); - let c = f64::from_bits(this.read_scalar(c)?.to_u64()?); - let res = a.mul_add(b, c); - this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; + let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = this.adjust_nan(res, &[a, b, c]); + this.write_scalar(res, dest)?; + } + + "powf32" => { + let [f1, f2] = check_arg_count(args)?; + let f1 = this.read_scalar(f1)?.to_f32()?; + let f2 = this.read_scalar(f2)?.to_f32()?; + // FIXME: Using host floats. + let res = f1.to_host().powf(f2.to_host()).to_soft(); + let res = this.adjust_nan(res, &[f1, f2]); + this.write_scalar(res, dest)?; + } + + "powf64" => { + let [f1, f2] = check_arg_count(args)?; + let f1 = this.read_scalar(f1)?.to_f64()?; + let f2 = this.read_scalar(f2)?.to_f64()?; + // FIXME: Using host floats. + let res = f1.to_host().powf(f2.to_host()).to_soft(); + let res = this.adjust_nan(res, &[f1, f2]); + this.write_scalar(res, dest)?; } "powif32" => { let [f, i] = check_arg_count(args)?; - // FIXME: Using host floats. - let f = f32::from_bits(this.read_scalar(f)?.to_u32()?); + let f = this.read_scalar(f)?.to_f32()?; let i = this.read_scalar(i)?.to_i32()?; - let res = f.powi(i); - this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; + // FIXME: Using host floats. + let res = f.to_host().powi(i).to_soft(); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; } "powif64" => { let [f, i] = check_arg_count(args)?; - // FIXME: Using host floats. - let f = f64::from_bits(this.read_scalar(f)?.to_u64()?); + let f = this.read_scalar(f)?.to_f64()?; let i = this.read_scalar(i)?.to_i32()?; - let res = f.powi(i); - this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; + // FIXME: Using host floats. + let res = f.to_host().powi(i).to_soft(); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; } "float_to_int_unchecked" => { diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 6ea034e2cda9d..99151e5df7c0d 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -249,6 +249,55 @@ fn test_f32() { check_all_outcomes(HashSet::from_iter([F32::nan(Neg, Signaling, all1_payload)]), || { F32::from(-all1_snan) }); + + // Intrinsics + let nan = F32::nan(Neg, Quiet, 0).as_f32(); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(f32::min(nan, nan)), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.sin()), + ); + check_all_outcomes( + HashSet::from_iter([ + F32::nan(Pos, Quiet, 0), + F32::nan(Neg, Quiet, 0), + F32::nan(Pos, Quiet, 1), + F32::nan(Neg, Quiet, 1), + F32::nan(Pos, Quiet, 2), + F32::nan(Neg, Quiet, 2), + F32::nan(Pos, Quiet, all1_payload), + F32::nan(Neg, Quiet, all1_payload), + F32::nan(Pos, Signaling, all1_payload), + F32::nan(Neg, Signaling, all1_payload), + ]), + || F32::from(just1.mul_add(F32::nan(Neg, Quiet, 2).as_f32(), all1_snan)), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.powf(nan)), + ); + check_all_outcomes( + HashSet::from_iter([1.0f32.into()]), + || F32::from(1.0f32.powf(nan)), // special `pow` rule + ); + check_all_outcomes( + HashSet::from_iter([ + F32::nan(Pos, Quiet, 0), + F32::nan(Neg, Quiet, 0), + F32::nan(Pos, Quiet, 1), + F32::nan(Neg, Quiet, 1), + F32::nan(Pos, Signaling, 1), + F32::nan(Neg, Signaling, 1), + ]), + || F32::from(1.0f32.powf(F32::nan(Pos, Signaling, 1).as_f32())), // unspecified `pow` case + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.powi(1)), + ); } fn test_f64() { @@ -309,6 +358,55 @@ fn test_f64() { ]), || F64::from(just1 % all1_snan), ); + + // Intrinsics + let nan = F64::nan(Neg, Quiet, 0).as_f64(); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(f64::min(nan, nan)), + ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.sin()), + ); + check_all_outcomes( + HashSet::from_iter([ + F64::nan(Pos, Quiet, 0), + F64::nan(Neg, Quiet, 0), + F64::nan(Pos, Quiet, 1), + F64::nan(Neg, Quiet, 1), + F64::nan(Pos, Quiet, 2), + F64::nan(Neg, Quiet, 2), + F64::nan(Pos, Quiet, all1_payload), + F64::nan(Neg, Quiet, all1_payload), + F64::nan(Pos, Signaling, all1_payload), + F64::nan(Neg, Signaling, all1_payload), + ]), + || F64::from(just1.mul_add(F64::nan(Neg, Quiet, 2).as_f64(), all1_snan)), + ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.powf(nan)), + ); + check_all_outcomes( + HashSet::from_iter([1.0f64.into()]), + || F64::from(1.0f64.powf(nan)), // special `pow` rule + ); + check_all_outcomes( + HashSet::from_iter([ + F64::nan(Pos, Quiet, 0), + F64::nan(Neg, Quiet, 0), + F64::nan(Pos, Quiet, 1), + F64::nan(Neg, Quiet, 1), + F64::nan(Pos, Signaling, 1), + F64::nan(Neg, Signaling, 1), + ]), + || F64::from(1.0f64.powf(F64::nan(Pos, Signaling, 1).as_f64())), // unspecified `pow` case + ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.powi(1)), + ); } fn test_casts() { From 0f98c0e6102cadfc8c0b759d09c7f1b73b07564c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Dec 2023 11:07:56 +0100 Subject: [PATCH 05/10] add NaN-nondet to libm functions --- src/tools/miri/src/shims/foreign_items.rs | 108 ++++++++++++---------- src/tools/miri/tests/pass/float_nan.rs | 40 ++++++++ 2 files changed, 101 insertions(+), 47 deletions(-) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 8ddfc05dd300a..e7b2a6823ed6e 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -23,6 +23,7 @@ use rustc_target::{ use super::backtrace::EvalContextExt as _; use crate::*; +use helpers::{ToHost, ToSoft}; /// Type of dynamic symbols (for `dlsym` et al) #[derive(Debug, Copy, Clone)] @@ -886,23 +887,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "tgammaf" => { let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let f = this.read_scalar(f)?.to_f32()?; // FIXME: Using host floats. - let f = f32::from_bits(this.read_scalar(f)?.to_u32()?); + let f_host = f.to_host(); let res = match link_name.as_str() { - "cbrtf" => f.cbrt(), - "coshf" => f.cosh(), - "sinhf" => f.sinh(), - "tanf" => f.tan(), - "tanhf" => f.tanh(), - "acosf" => f.acos(), - "asinf" => f.asin(), - "atanf" => f.atan(), - "log1pf" => f.ln_1p(), - "expm1f" => f.exp_m1(), - "tgammaf" => f.gamma(), + "cbrtf" => f_host.cbrt(), + "coshf" => f_host.cosh(), + "sinhf" => f_host.sinh(), + "tanf" => f_host.tan(), + "tanhf" => f_host.tanh(), + "acosf" => f_host.acos(), + "asinf" => f_host.asin(), + "atanf" => f_host.atan(), + "log1pf" => f_host.ln_1p(), + "expm1f" => f_host.exp_m1(), + "tgammaf" => f_host.gamma(), _ => bug!(), }; - this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; + let res = res.to_soft(); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; } #[rustfmt::skip] | "_hypotf" @@ -911,19 +915,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "fdimf" => { let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let f1 = this.read_scalar(f1)?.to_f32()?; + let f2 = this.read_scalar(f2)?.to_f32()?; // underscore case for windows, here and below // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019) // FIXME: Using host floats. - let f1 = f32::from_bits(this.read_scalar(f1)?.to_u32()?); - let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?); let res = match link_name.as_str() { - "_hypotf" | "hypotf" => f1.hypot(f2), - "atan2f" => f1.atan2(f2), + "_hypotf" | "hypotf" => f1.to_host().hypot(f2.to_host()).to_soft(), + "atan2f" => f1.to_host().atan2(f2.to_host()).to_soft(), #[allow(deprecated)] - "fdimf" => f1.abs_sub(f2), + "fdimf" => f1.to_host().abs_sub(f2.to_host()).to_soft(), _ => bug!(), }; - this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; + let res = this.adjust_nan(res, &[f1, f2]); + this.write_scalar(res, dest)?; } #[rustfmt::skip] | "cbrt" @@ -939,23 +944,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "tgamma" => { let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let f = this.read_scalar(f)?.to_f64()?; // FIXME: Using host floats. - let f = f64::from_bits(this.read_scalar(f)?.to_u64()?); + let f_host = f.to_host(); let res = match link_name.as_str() { - "cbrt" => f.cbrt(), - "cosh" => f.cosh(), - "sinh" => f.sinh(), - "tan" => f.tan(), - "tanh" => f.tanh(), - "acos" => f.acos(), - "asin" => f.asin(), - "atan" => f.atan(), - "log1p" => f.ln_1p(), - "expm1" => f.exp_m1(), - "tgamma" => f.gamma(), + "cbrt" => f_host.cbrt(), + "cosh" => f_host.cosh(), + "sinh" => f_host.sinh(), + "tan" => f_host.tan(), + "tanh" => f_host.tanh(), + "acos" => f_host.acos(), + "asin" => f_host.asin(), + "atan" => f_host.atan(), + "log1p" => f_host.ln_1p(), + "expm1" => f_host.exp_m1(), + "tgamma" => f_host.gamma(), _ => bug!(), }; - this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; + let res = res.to_soft(); + let res = this.adjust_nan(res, &[f]); + this.write_scalar(res, dest)?; } #[rustfmt::skip] | "_hypot" @@ -964,17 +972,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { | "fdim" => { let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let f1 = this.read_scalar(f1)?.to_f64()?; + let f2 = this.read_scalar(f2)?.to_f64()?; + // underscore case for windows, here and below + // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019) // FIXME: Using host floats. - let f1 = f64::from_bits(this.read_scalar(f1)?.to_u64()?); - let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?); let res = match link_name.as_str() { - "_hypot" | "hypot" => f1.hypot(f2), - "atan2" => f1.atan2(f2), + "_hypot" | "hypot" => f1.to_host().hypot(f2.to_host()).to_soft(), + "atan2" => f1.to_host().atan2(f2.to_host()).to_soft(), #[allow(deprecated)] - "fdim" => f1.abs_sub(f2), + "fdim" => f1.to_host().abs_sub(f2.to_host()).to_soft(), _ => bug!(), }; - this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; + let res = this.adjust_nan(res, &[f1, f2]); + this.write_scalar(res, dest)?; } #[rustfmt::skip] | "_ldexp" @@ -987,27 +998,30 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let exp = this.read_scalar(exp)?.to_i32()?; let res = x.scalbn(exp); - this.write_scalar(Scalar::from_f64(res), dest)?; + let res = this.adjust_nan(res, &[x]); + this.write_scalar(res, dest)?; } "lgammaf_r" => { let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // FIXME: Using host floats. - let x = f32::from_bits(this.read_scalar(x)?.to_u32()?); + let x = this.read_scalar(x)?.to_f32()?; let signp = this.deref_pointer(signp)?; - let (res, sign) = x.ln_gamma(); + // FIXME: Using host floats. + let (res, sign) = x.to_host().ln_gamma(); this.write_int(sign, &signp)?; - this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?; + let res = this.adjust_nan(res.to_soft(), &[x]); + this.write_scalar(res, dest)?; } "lgamma_r" => { let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // FIXME: Using host floats. - let x = f64::from_bits(this.read_scalar(x)?.to_u64()?); + let x = this.read_scalar(x)?.to_f64()?; let signp = this.deref_pointer(signp)?; - let (res, sign) = x.ln_gamma(); + // FIXME: Using host floats. + let (res, sign) = x.to_host().ln_gamma(); this.write_int(sign, &signp)?; - this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?; + let res = this.adjust_nan(res.to_soft(), &[x]); + this.write_scalar(res, dest)?; } // LLVM intrinsics diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 99151e5df7c0d..5e717bdca0072 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -1,8 +1,16 @@ +#![feature(float_gamma)] use std::collections::HashSet; use std::fmt; use std::hash::Hash; use std::hint::black_box; +fn ldexp(a: f64, b: i32) -> f64 { + extern "C" { + fn ldexp(x: f64, n: i32) -> f64; + } + unsafe { ldexp(a, b) } +} + #[derive(Clone, Copy, Debug, PartialEq, Eq)] enum Sign { Neg = 1, @@ -298,6 +306,20 @@ fn test_f32() { HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), || F32::from(nan.powi(1)), ); + + // libm functions + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.sinh()), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.atan2(nan)), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(nan.ln_gamma().0), + ); } fn test_f64() { @@ -407,6 +429,24 @@ fn test_f64() { HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), || F64::from(nan.powi(1)), ); + + // libm functions + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.sinh()), + ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.atan2(nan)), + ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(ldexp(nan, 1)), + ); + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(nan.ln_gamma().0), + ); } fn test_casts() { From ee42d1eb9f5983f8f281e87989617caba45007b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Dec 2023 12:14:01 +0100 Subject: [PATCH 06/10] NaN non-determinism for SIMD intrinsics --- src/tools/miri/src/shims/intrinsics/simd.rs | 162 +++++++++++--------- src/tools/miri/tests/pass/float_nan.rs | 58 ++++++- 2 files changed, 145 insertions(+), 75 deletions(-) diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 2c8493d8aad1a..d749182ed5e71 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -5,10 +5,17 @@ use rustc_span::{sym, Symbol}; use rustc_target::abi::{Endian, HasDataLayout}; use crate::helpers::{ - bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool, + bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool, ToHost, + ToSoft, }; use crate::*; +#[derive(Copy, Clone)] +pub(crate) enum MinMax { + Min, + Max, +} + impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// Calls the simd intrinsic `intrinsic`; the `simd_` prefix has already been removed. @@ -67,13 +74,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let op = this.read_immediate(&this.project_index(&op, i)?)?; let dest = this.project_index(&dest, i)?; let val = match which { - Op::MirOp(mir_op) => this.wrapping_unary_op(mir_op, &op)?.to_scalar(), + Op::MirOp(mir_op) => { + // This already does NaN adjustments + this.wrapping_unary_op(mir_op, &op)?.to_scalar() + } Op::Abs => { // Works for f32 and f64. let ty::Float(float_ty) = op.layout.ty.kind() else { span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name) }; let op = op.to_scalar(); + // "Bitwise" operation, no NaN adjustments match float_ty { FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()), FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()), @@ -86,14 +97,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // FIXME using host floats match float_ty { FloatTy::F32 => { - let f = f32::from_bits(op.to_scalar().to_u32()?); - let res = f.sqrt(); - Scalar::from_u32(res.to_bits()) + let f = op.to_scalar().to_f32()?; + let res = f.to_host().sqrt().to_soft(); + let res = this.adjust_nan(res, &[f]); + Scalar::from(res) } FloatTy::F64 => { - let f = f64::from_bits(op.to_scalar().to_u64()?); - let res = f.sqrt(); - Scalar::from_u64(res.to_bits()) + let f = op.to_scalar().to_f64()?; + let res = f.to_host().sqrt().to_soft(); + let res = this.adjust_nan(res, &[f]); + Scalar::from(res) } } } @@ -105,11 +118,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { FloatTy::F32 => { let f = op.to_scalar().to_f32()?; let res = f.round_to_integral(rounding).value; + let res = this.adjust_nan(res, &[f]); Scalar::from_f32(res) } FloatTy::F64 => { let f = op.to_scalar().to_f64()?; let res = f.round_to_integral(rounding).value; + let res = this.adjust_nan(res, &[f]); Scalar::from_f64(res) } } @@ -157,8 +172,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { enum Op { MirOp(BinOp), SaturatingOp(BinOp), - FMax, - FMin, + FMinMax(MinMax), WrappingOffset, } let which = match intrinsic_name { @@ -178,8 +192,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "le" => Op::MirOp(BinOp::Le), "gt" => Op::MirOp(BinOp::Gt), "ge" => Op::MirOp(BinOp::Ge), - "fmax" => Op::FMax, - "fmin" => Op::FMin, + "fmax" => Op::FMinMax(MinMax::Max), + "fmin" => Op::FMinMax(MinMax::Min), "saturating_add" => Op::SaturatingOp(BinOp::Add), "saturating_sub" => Op::SaturatingOp(BinOp::Sub), "arith_offset" => Op::WrappingOffset, @@ -192,6 +206,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let dest = this.project_index(&dest, i)?; let val = match which { Op::MirOp(mir_op) => { + // This does NaN adjustments. let (val, overflowed) = this.overflowing_binary_op(mir_op, &left, &right)?; if matches!(mir_op, BinOp::Shl | BinOp::Shr) { // Shifts have extra UB as SIMD operations that the MIR binop does not have. @@ -225,11 +240,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let offset_ptr = ptr.wrapping_signed_offset(offset_bytes, this); Scalar::from_maybe_pointer(offset_ptr, this) } - Op::FMax => { - fmax_op(&left, &right)? - } - Op::FMin => { - fmin_op(&left, &right)? + Op::FMinMax(op) => { + this.fminmax_op(op, &left, &right)? } }; this.write_scalar(val, &dest)?; @@ -259,18 +271,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { }; let val = match float_ty { FloatTy::F32 => { - let a = f32::from_bits(a.to_u32()?); - let b = f32::from_bits(b.to_u32()?); - let c = f32::from_bits(c.to_u32()?); - let res = a.mul_add(b, c); - Scalar::from_u32(res.to_bits()) + let a = a.to_f32()?; + let b = b.to_f32()?; + let c = c.to_f32()?; + let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = this.adjust_nan(res, &[a, b, c]); + Scalar::from(res) } FloatTy::F64 => { - let a = f64::from_bits(a.to_u64()?); - let b = f64::from_bits(b.to_u64()?); - let c = f64::from_bits(c.to_u64()?); - let res = a.mul_add(b, c); - Scalar::from_u64(res.to_bits()) + let a = a.to_f64()?; + let b = b.to_f64()?; + let c = c.to_f64()?; + let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft(); + let res = this.adjust_nan(res, &[a, b, c]); + Scalar::from(res) } }; this.write_scalar(val, &dest)?; @@ -295,8 +309,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { enum Op { MirOp(BinOp), MirOpBool(BinOp), - Max, - Min, + MinMax(MinMax), } let which = match intrinsic_name { "reduce_and" => Op::MirOp(BinOp::BitAnd), @@ -304,8 +317,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "reduce_xor" => Op::MirOp(BinOp::BitXor), "reduce_any" => Op::MirOpBool(BinOp::BitOr), "reduce_all" => Op::MirOpBool(BinOp::BitAnd), - "reduce_max" => Op::Max, - "reduce_min" => Op::Min, + "reduce_max" => Op::MinMax(MinMax::Max), + "reduce_min" => Op::MinMax(MinMax::Min), _ => unreachable!(), }; @@ -325,24 +338,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let op = imm_from_bool(simd_element_to_bool(op)?); this.wrapping_binary_op(mir_op, &res, &op)? } - Op::Max => { - if matches!(res.layout.ty.kind(), ty::Float(_)) { - ImmTy::from_scalar(fmax_op(&res, &op)?, res.layout) - } else { - // Just boring integers, so NaNs to worry about - if this.wrapping_binary_op(BinOp::Ge, &res, &op)?.to_scalar().to_bool()? { - res - } else { - op - } - } - } - Op::Min => { + Op::MinMax(mmop) => { if matches!(res.layout.ty.kind(), ty::Float(_)) { - ImmTy::from_scalar(fmin_op(&res, &op)?, res.layout) + ImmTy::from_scalar(this.fminmax_op(mmop, &res, &op)?, res.layout) } else { // Just boring integers, so NaNs to worry about - if this.wrapping_binary_op(BinOp::Le, &res, &op)?.to_scalar().to_bool()? { + let mirop = match mmop { + MinMax::Min => BinOp::Le, + MinMax::Max => BinOp::Ge, + }; + if this.wrapping_binary_op(mirop, &res, &op)?.to_scalar().to_bool()? { res } else { op @@ -709,6 +714,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } Ok(()) } + + fn fminmax_op( + &self, + op: MinMax, + left: &ImmTy<'tcx, Provenance>, + right: &ImmTy<'tcx, Provenance>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_ref(); + assert_eq!(left.layout.ty, right.layout.ty); + let ty::Float(float_ty) = left.layout.ty.kind() else { + bug!("fmax operand is not a float") + }; + let left = left.to_scalar(); + let right = right.to_scalar(); + Ok(match float_ty { + FloatTy::F32 => { + let left = left.to_f32()?; + let right = right.to_f32()?; + let res = match op { + MinMax::Min => left.min(right), + MinMax::Max => left.max(right), + }; + let res = this.adjust_nan(res, &[left, right]); + Scalar::from_f32(res) + } + FloatTy::F64 => { + let left = left.to_f64()?; + let right = right.to_f64()?; + let res = match op { + MinMax::Min => left.min(right), + MinMax::Max => left.max(right), + }; + let res = this.adjust_nan(res, &[left, right]); + Scalar::from_f64(res) + } + }) + } } fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 { @@ -719,31 +761,3 @@ fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 { Endian::Big => vec_len - 1 - idx, // reverse order of bits } } - -fn fmax_op<'tcx>( - left: &ImmTy<'tcx, Provenance>, - right: &ImmTy<'tcx, Provenance>, -) -> InterpResult<'tcx, Scalar> { - assert_eq!(left.layout.ty, right.layout.ty); - let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmax operand is not a float") }; - let left = left.to_scalar(); - let right = right.to_scalar(); - Ok(match float_ty { - FloatTy::F32 => Scalar::from_f32(left.to_f32()?.max(right.to_f32()?)), - FloatTy::F64 => Scalar::from_f64(left.to_f64()?.max(right.to_f64()?)), - }) -} - -fn fmin_op<'tcx>( - left: &ImmTy<'tcx, Provenance>, - right: &ImmTy<'tcx, Provenance>, -) -> InterpResult<'tcx, Scalar> { - assert_eq!(left.layout.ty, right.layout.ty); - let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmin operand is not a float") }; - let left = left.to_scalar(); - let right = right.to_scalar(); - Ok(match float_ty { - FloatTy::F32 => Scalar::from_f32(left.to_f32()?.min(right.to_f32()?)), - FloatTy::F64 => Scalar::from_f64(left.to_f64()?.min(right.to_f64()?)), - }) -} diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index 5e717bdca0072..fff103a776f45 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -1,4 +1,4 @@ -#![feature(float_gamma)] +#![feature(float_gamma, portable_simd, core_intrinsics, platform_intrinsics)] use std::collections::HashSet; use std::fmt; use std::hash::Hash; @@ -535,6 +535,61 @@ fn test_casts() { ); } +fn test_simd() { + use std::intrinsics::simd::*; + use std::simd::*; + + extern "platform-intrinsic" { + fn simd_fsqrt(x: T) -> T; + fn simd_ceil(x: T) -> T; + fn simd_fma(x: T, y: T, z: T) -> T; + } + + let nan = F32::nan(Neg, Quiet, 0).as_f32(); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_div(f32x4::splat(0.0), f32x4::splat(0.0)) }[0]), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_fmin(f32x4::splat(nan), f32x4::splat(nan)) }[0]), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_fmax(f32x4::splat(nan), f32x4::splat(nan)) }[0]), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || { + F32::from( + unsafe { simd_fma(f32x4::splat(nan), f32x4::splat(nan), f32x4::splat(nan)) }[0], + ) + }, + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_reduce_add_ordered::<_, f32>(f32x4::splat(nan), nan) }), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_reduce_max::<_, f32>(f32x4::splat(nan)) }), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_fsqrt(f32x4::splat(nan)) }[0]), + ); + check_all_outcomes( + HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), + || F32::from(unsafe { simd_ceil(f32x4::splat(nan)) }[0]), + ); + + // Casts + check_all_outcomes( + HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), + || F64::from(unsafe { simd_cast::(f32x4::splat(nan)) }[0]), + ); +} + fn main() { // Check our constants against std, just to be sure. // We add 1 since our numbers are the number of bits stored @@ -546,4 +601,5 @@ fn main() { test_f32(); test_f64(); test_casts(); + test_simd(); } From 771e47929f55febce4125c34f2641089f01ece52 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 28 Dec 2023 12:56:07 +0100 Subject: [PATCH 07/10] don't test unspecified case --- src/tools/miri/tests/pass/float_nan.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs index fff103a776f45..207ce70fb20e3 100644 --- a/src/tools/miri/tests/pass/float_nan.rs +++ b/src/tools/miri/tests/pass/float_nan.rs @@ -291,17 +291,6 @@ fn test_f32() { HashSet::from_iter([1.0f32.into()]), || F32::from(1.0f32.powf(nan)), // special `pow` rule ); - check_all_outcomes( - HashSet::from_iter([ - F32::nan(Pos, Quiet, 0), - F32::nan(Neg, Quiet, 0), - F32::nan(Pos, Quiet, 1), - F32::nan(Neg, Quiet, 1), - F32::nan(Pos, Signaling, 1), - F32::nan(Neg, Signaling, 1), - ]), - || F32::from(1.0f32.powf(F32::nan(Pos, Signaling, 1).as_f32())), // unspecified `pow` case - ); check_all_outcomes( HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]), || F32::from(nan.powi(1)), @@ -414,17 +403,6 @@ fn test_f64() { HashSet::from_iter([1.0f64.into()]), || F64::from(1.0f64.powf(nan)), // special `pow` rule ); - check_all_outcomes( - HashSet::from_iter([ - F64::nan(Pos, Quiet, 0), - F64::nan(Neg, Quiet, 0), - F64::nan(Pos, Quiet, 1), - F64::nan(Neg, Quiet, 1), - F64::nan(Pos, Signaling, 1), - F64::nan(Neg, Signaling, 1), - ]), - || F64::from(1.0f64.powf(F64::nan(Pos, Signaling, 1).as_f64())), // unspecified `pow` case - ); check_all_outcomes( HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]), || F64::from(nan.powi(1)), From 4da47a418061fb429869ff1a2ad284f2e674856d Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Thu, 28 Dec 2023 15:06:07 -0500 Subject: [PATCH 08/10] Fix integer overflow ICEs from round_up_to_next_multiple_of --- src/tools/miri/src/helpers.rs | 8 -------- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/shims/intrinsics/simd.rs | 9 +++------ src/tools/miri/src/shims/unix/mem.rs | 22 ++++++++++++++++++--- src/tools/miri/tests/pass-dep/shims/mmap.rs | 21 ++++++++++++++++++++ 5 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 98f646da6b69f..14ba69b898b11 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1233,11 +1233,3 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult< _ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"), }) } - -// This looks like something that would be nice to have in the standard library... -pub(crate) fn round_to_next_multiple_of(x: u64, divisor: u64) -> u64 { - assert_ne!(divisor, 0); - // divisor is nonzero; multiplication cannot overflow since we just divided - #[allow(clippy::arithmetic_side_effects)] - return (x.checked_add(divisor - 1).unwrap() / divisor) * divisor; -} diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 4e9febf02050c..cacd02bbfaee1 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -11,6 +11,7 @@ #![feature(round_ties_even)] #![feature(let_chains)] #![feature(lint_reasons)] +#![feature(int_roundings)] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index d749182ed5e71..ea2d104694af7 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -4,10 +4,7 @@ use rustc_middle::{mir, ty, ty::FloatTy}; use rustc_span::{sym, Symbol}; use rustc_target::abi::{Endian, HasDataLayout}; -use crate::helpers::{ - bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool, ToHost, - ToSoft, -}; +use crate::helpers::{bool_to_simd_element, check_arg_count, simd_element_to_bool, ToHost, ToSoft}; use crate::*; #[derive(Copy, Clone)] @@ -407,7 +404,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let (yes, yes_len) = this.operand_to_simd(yes)?; let (no, no_len) = this.operand_to_simd(no)?; let (dest, dest_len) = this.place_to_simd(dest)?; - let bitmask_len = round_to_next_multiple_of(dest_len, 8); + let bitmask_len = dest_len.next_multiple_of(8); // The mask must be an integer or an array. assert!( @@ -453,7 +450,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "bitmask" => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; - let bitmask_len = round_to_next_multiple_of(op_len, 8); + let bitmask_len = op_len.next_multiple_of(8); // Returns either an unsigned integer or array of `u8`. assert!( diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs index 5aa514715bc3a..d7dc17fa89f13 100644 --- a/src/tools/miri/src/shims/unix/mem.rs +++ b/src/tools/miri/src/shims/unix/mem.rs @@ -14,7 +14,7 @@ //! munmap shim which would partily unmap a region of address space previously mapped by mmap will //! report UB. -use crate::{helpers::round_to_next_multiple_of, *}; +use crate::*; use rustc_target::abi::Size; impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} @@ -96,7 +96,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } let align = this.machine.page_align(); - let map_length = round_to_next_multiple_of(length, this.machine.page_size); + let Some(map_length) = length.checked_next_multiple_of(this.machine.page_size) else { + this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?; + return Ok(this.eval_libc("MAP_FAILED")); + }; + if map_length > this.target_usize_max() { + this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?; + return Ok(this.eval_libc("MAP_FAILED")); + } let ptr = this.allocate_ptr(Size::from_bytes(map_length), align, MiriMemoryKind::Mmap.into())?; @@ -129,7 +136,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { return Ok(Scalar::from_i32(-1)); } - let length = Size::from_bytes(round_to_next_multiple_of(length, this.machine.page_size)); + let Some(length) = length.checked_next_multiple_of(this.machine.page_size) else { + this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?; + return Ok(Scalar::from_i32(-1)); + }; + if length > this.target_usize_max() { + this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?; + return Ok(this.eval_libc("MAP_FAILED")); + } + + let length = Size::from_bytes(length); this.deallocate_ptr( addr, Some((length, this.machine.page_align())), diff --git a/src/tools/miri/tests/pass-dep/shims/mmap.rs b/src/tools/miri/tests/pass-dep/shims/mmap.rs index 518f2ea3e6f1c..e19f54d0687df 100644 --- a/src/tools/miri/tests/pass-dep/shims/mmap.rs +++ b/src/tools/miri/tests/pass-dep/shims/mmap.rs @@ -90,9 +90,30 @@ fn test_mmap() { assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::ENOTSUP); } + // We report an error for mappings whose length cannot be rounded up to a multiple of + // the page size. + let ptr = unsafe { + libc::mmap( + ptr::null_mut(), + usize::MAX - 1, + libc::PROT_READ | libc::PROT_WRITE, + libc::MAP_PRIVATE | libc::MAP_ANONYMOUS, + -1, + 0, + ) + }; + assert_eq!(ptr, libc::MAP_FAILED); + + // We report an error when trying to munmap an address which is not a multiple of the page size let res = unsafe { libc::munmap(ptr::invalid_mut(1), page_size) }; assert_eq!(res, -1); assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); + + // We report an error when trying to munmap a length that cannot be rounded up to a multiple of + // the page size. + let res = unsafe { libc::munmap(ptr::invalid_mut(page_size), usize::MAX - 1) }; + assert_eq!(res, -1); + assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL); } #[cfg(target_os = "linux")] From 109ada8e9e9aa2abcc5c7d5256320ee186bac859 Mon Sep 17 00:00:00 2001 From: DrMeepster <19316085+DrMeepster@users.noreply.github.com> Date: Fri, 29 Dec 2023 12:33:27 -0800 Subject: [PATCH 09/10] undo some lockfile changes, add explicit types to tests --- src/tools/miri/test_dependencies/Cargo.lock | 88 +++++++++---------- .../concurrency/windows_join_detached.rs | 4 +- .../concurrency/windows_condvar_shared.rs | 34 +++---- .../concurrency/windows_detach_terminated.rs | 6 +- .../pass-dep/concurrency/windows_init_once.rs | 64 +++++--------- .../concurrency/windows_join_multiple.rs | 4 +- 6 files changed, 91 insertions(+), 109 deletions(-) diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock index 4700b519495fe..7b7bb41fc4a53 100644 --- a/src/tools/miri/test_dependencies/Cargo.lock +++ b/src/tools/miri/test_dependencies/Cargo.lock @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "js-sys", @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "hermit-abi" @@ -109,24 +109,24 @@ checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.151" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -169,7 +169,7 @@ name = "miri-test-deps" version = "0.1.0" dependencies = [ "getrandom 0.1.16", - "getrandom 0.2.11", + "getrandom 0.2.10", "libc", "num_cpus", "page_size", @@ -190,18 +190,18 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "page_size" @@ -225,9 +225,9 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", @@ -250,9 +250,9 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -293,14 +293,14 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.10", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] @@ -328,15 +328,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" dependencies = [ "libc", "windows-sys 0.48.0", @@ -344,9 +344,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.43" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -355,9 +355,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.35.1" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ "backtrace", "bytes", @@ -374,9 +374,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", @@ -403,9 +403,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -413,9 +413,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", @@ -428,9 +428,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -438,9 +438,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", @@ -451,9 +451,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "winapi" diff --git a/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs index 8befd3c442a08..0e9eb24459c3e 100644 --- a/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs +++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs @@ -6,13 +6,13 @@ use std::os::windows::io::AsRawHandle; use std::thread; -use windows_sys::Win32::Foundation::CloseHandle; +use windows_sys::Win32::Foundation::{CloseHandle, HANDLE}; fn main() { let thread = thread::spawn(|| ()); unsafe { - assert_ne!(CloseHandle(thread.as_raw_handle() as _), 0); + assert_ne!(CloseHandle(thread.as_raw_handle() as HANDLE), 0); } thread.join().unwrap(); diff --git a/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs index eb32f7b66b2fb..5bff9098a58bd 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs @@ -2,15 +2,19 @@ // We are making scheduler assumptions here. //@compile-flags: -Zmiri-preemption-rate=0 -use std::mem::MaybeUninit; +use std::ptr::null_mut; use std::thread; use windows_sys::Win32::System::Threading::{ AcquireSRWLockExclusive, AcquireSRWLockShared, ReleaseSRWLockExclusive, ReleaseSRWLockShared, - SleepConditionVariableSRW, WakeAllConditionVariable, CONDITION_VARIABLE_LOCKMODE_SHARED, - INFINITE, + SleepConditionVariableSRW, WakeAllConditionVariable, CONDITION_VARIABLE, + CONDITION_VARIABLE_LOCKMODE_SHARED, INFINITE, SRWLOCK, }; +// not in windows-sys +const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: null_mut() }; +const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: null_mut() }; + #[derive(Copy, Clone)] struct SendPtr(*mut T); @@ -20,11 +24,11 @@ unsafe impl Send for SendPtr {} fn all_shared() { println!("all_shared"); - let mut lock = MaybeUninit::zeroed(); - let mut condvar = MaybeUninit::zeroed(); + let mut lock = SRWLOCK_INIT; + let mut condvar = CONDITION_VARIABLE_INIT; - let lock_ptr = SendPtr(lock.as_mut_ptr()); - let condvar_ptr = SendPtr(condvar.as_mut_ptr()); + let lock_ptr = SendPtr(&mut lock); + let condvar_ptr = SendPtr(&mut condvar); let mut handles = Vec::with_capacity(10); @@ -92,11 +96,11 @@ fn all_shared() { fn shared_sleep_and_exclusive_lock() { println!("shared_sleep_and_exclusive_lock"); - let mut lock = MaybeUninit::zeroed(); - let mut condvar = MaybeUninit::zeroed(); + let mut lock = SRWLOCK_INIT; + let mut condvar = CONDITION_VARIABLE_INIT; - let lock_ptr = SendPtr(lock.as_mut_ptr()); - let condvar_ptr = SendPtr(condvar.as_mut_ptr()); + let lock_ptr = SendPtr(&mut lock); + let condvar_ptr = SendPtr(&mut condvar); let mut waiters = Vec::with_capacity(5); for i in 0..5 { @@ -153,11 +157,11 @@ fn shared_sleep_and_exclusive_lock() { fn exclusive_sleep_and_shared_lock() { println!("exclusive_sleep_and_shared_lock"); - let mut lock = MaybeUninit::zeroed(); - let mut condvar = MaybeUninit::zeroed(); + let mut lock = SRWLOCK_INIT; + let mut condvar = CONDITION_VARIABLE_INIT; - let lock_ptr = SendPtr(lock.as_mut_ptr()); - let condvar_ptr = SendPtr(condvar.as_mut_ptr()); + let lock_ptr = SendPtr(&mut lock); + let condvar_ptr = SendPtr(&mut condvar); let mut handles = Vec::with_capacity(10); for i in 0..5 { diff --git a/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs index a11799815e0f4..3d4f8c5e1c063 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs @@ -5,15 +5,15 @@ use std::os::windows::io::IntoRawHandle; use std::thread; -use windows_sys::Win32::Foundation::CloseHandle; +use windows_sys::Win32::Foundation::{CloseHandle, HANDLE}; fn main() { - let thread = thread::spawn(|| {}).into_raw_handle(); + let thread = thread::spawn(|| {}).into_raw_handle() as HANDLE; // this yield ensures that `thread` is terminated by this point thread::yield_now(); unsafe { - assert_ne!(CloseHandle(thread as _), 0); + assert_ne!(CloseHandle(thread), 0); } } diff --git a/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs index 57d2a5657a3eb..5e33617f98ad1 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs @@ -2,75 +2,59 @@ // We are making scheduler assumptions here. //@compile-flags: -Zmiri-preemption-rate=0 -use std::mem::MaybeUninit; use std::ptr::null_mut; use std::thread; use windows_sys::Win32::Foundation::{FALSE, TRUE}; use windows_sys::Win32::System::Threading::{ - InitOnceBeginInitialize, InitOnceComplete, INIT_ONCE_INIT_FAILED, + InitOnceBeginInitialize, InitOnceComplete, INIT_ONCE, INIT_ONCE_INIT_FAILED, }; +// not in windows-sys +const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: null_mut() }; + #[derive(Copy, Clone)] struct SendPtr(*mut T); unsafe impl Send for SendPtr {} fn single_thread() { - let mut init_once = MaybeUninit::zeroed(); + let mut init_once = INIT_ONCE_STATIC_INIT; let mut pending = 0; unsafe { - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, TRUE); - assert_eq!(InitOnceComplete(init_once.as_mut_ptr(), 0, null_mut()), TRUE); + assert_eq!(InitOnceComplete(&mut init_once, 0, null_mut()), TRUE); - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, FALSE); } - let mut init_once = MaybeUninit::zeroed(); + let mut init_once = INIT_ONCE_STATIC_INIT; unsafe { - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, TRUE); - assert_eq!( - InitOnceComplete(init_once.as_mut_ptr(), INIT_ONCE_INIT_FAILED, null_mut()), - TRUE - ); + assert_eq!(InitOnceComplete(&mut init_once, INIT_ONCE_INIT_FAILED, null_mut()), TRUE); - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, TRUE); } } fn block_until_complete() { - let mut init_once = MaybeUninit::zeroed(); + let mut init_once = INIT_ONCE_STATIC_INIT; let mut pending = 0; unsafe { - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, TRUE); } - let init_once_ptr = SendPtr(init_once.as_mut_ptr()); + let init_once_ptr = SendPtr(&mut init_once); let waiter = move || unsafe { let init_once_ptr = init_once_ptr; // avoid field capture @@ -99,18 +83,15 @@ fn block_until_complete() { } fn retry_on_fail() { - let mut init_once = MaybeUninit::zeroed(); + let mut init_once = INIT_ONCE_STATIC_INIT; let mut pending = 0; unsafe { - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, TRUE); } - let init_once_ptr = SendPtr(init_once.as_mut_ptr()); + let init_once_ptr = SendPtr(&mut init_once); let waiter = move || unsafe { let init_once_ptr = init_once_ptr; // avoid field capture @@ -144,18 +125,15 @@ fn retry_on_fail() { } fn no_data_race_after_complete() { - let mut init_once = MaybeUninit::zeroed(); + let mut init_once = INIT_ONCE_STATIC_INIT; let mut pending = 0; unsafe { - assert_eq!( - InitOnceBeginInitialize(init_once.as_mut_ptr(), 0, &mut pending, null_mut()), - TRUE - ); + assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE); assert_eq!(pending, TRUE); } - let init_once_ptr = SendPtr(init_once.as_mut_ptr()); + let init_once_ptr = SendPtr(&mut init_once); let mut place = 0; let place_ptr = SendPtr(&mut place); diff --git a/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs index fb0fbc307fb9b..bff59591a94ad 100644 --- a/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs +++ b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs @@ -6,7 +6,7 @@ use std::os::windows::io::IntoRawHandle; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; -use windows_sys::Win32::Foundation::WAIT_OBJECT_0; +use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0}; use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE}; fn main() { @@ -17,7 +17,7 @@ fn main() { thread::yield_now(); } }) - .into_raw_handle() as _; + .into_raw_handle() as HANDLE; let waiter = move || unsafe { assert_eq!(WaitForSingleObject(blocker, INFINITE), WAIT_OBJECT_0); From 5aa15b6ee7ced4cb99fe119165d1b4a87a1126f2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 4 Jan 2024 12:30:38 +0100 Subject: [PATCH 10/10] miri: do not forward RUSTFLAGS to deps build --- src/tools/miri/tests/compiletest.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 3394c4a49f836..074808b11227f 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -111,6 +111,8 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`. ]); config.dependency_builder.args = builder_args.into_iter().map(Into::into).collect(); + // Reset `RUSTFLAGS` to work around . + config.dependency_builder.envs.push(("RUSTFLAGS".into(), None)); } config }