From abdfe4a79af1367fa0873329ba44dfddeb2d6387 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 18 Nov 2023 08:02:06 +0100 Subject: [PATCH 01/22] miri script: fix RUSTC_GIT error message --- src/tools/miri/miri-script/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index c24035ae086..e4789c696b3 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -286,7 +286,7 @@ impl Command { "This will pull a copy of the rust-lang/rust history into this Miri checkout, growing it by about 1GB." ); print!( - "To avoid that, abort now and set the `--rustc-git` flag to an existing rustc checkout. Proceed? [y/N] " + "To avoid that, abort now and set the `RUSTC_GIT` environment variable to an existing rustc checkout. Proceed? [y/N] " ); std::io::stdout().flush()?; let mut answer = String::new(); From eba8d293022706412c290ebe2d4c4ad85b550689 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 18 Nov 2023 15:55:58 +0100 Subject: [PATCH 02/22] cargo-miri: when verbose, print where the sysroot is being built --- src/tools/miri/cargo-miri/src/setup.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/cargo-miri/src/setup.rs b/src/tools/miri/cargo-miri/src/setup.rs index d921741d5de..8ae5b8c3e82 100644 --- a/src/tools/miri/cargo-miri/src/setup.rs +++ b/src/tools/miri/cargo-miri/src/setup.rs @@ -2,6 +2,7 @@ use std::env; use std::ffi::OsStr; +use std::fmt::Write; use std::path::PathBuf; use std::process::{self, Command}; @@ -140,12 +141,20 @@ pub fn setup( // Do the build. if print_sysroot { // Be silent. - } else if only_setup { - // We want to be explicit. - eprintln!("Preparing a sysroot for Miri (target: {target})..."); } else { - // We want to be quiet, but still let the user know that something is happening. - eprint!("Preparing a sysroot for Miri (target: {target})... "); + let mut msg = String::new(); + write!(msg, "Preparing a sysroot for Miri (target: {target})").unwrap(); + if verbose > 0 { + write!(msg, " in {}", sysroot_dir.display()).unwrap(); + } + write!(msg, "...").unwrap(); + if only_setup { + // We want to be explicit. + eprintln!("{msg}"); + } else { + // We want to be quiet, but still let the user know that something is happening. + eprint!("{msg} "); + } } SysrootBuilder::new(&sysroot_dir, target) .build_mode(BuildMode::Check) From cee4c575f224d12e8b4d5258b2006e9109b42035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io> Date: Sun, 19 Nov 2023 19:18:52 +0100 Subject: [PATCH 03/22] Improve wording of `intrinsics-x86-*.rs` header --- src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs | 2 +- src/tools/miri/tests/pass/intrinsics-x86-avx512.rs | 2 +- src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs | 2 +- src/tools/miri/tests/pass/intrinsics-x86-sse41.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs index 090b1db0af0..55d1bacdf45 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-aes-vaes.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs index c38158dc797..394412a2354 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx512.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs index 0805d9bc300..7566be4431b 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse3-ssse3.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm diff --git a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs b/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs index 8c565a2d6e0..13856d29d3f 100644 --- a/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs +++ b/src/tools/miri/tests/pass/intrinsics-x86-sse41.rs @@ -1,5 +1,5 @@ // Ignore everything except x86 and x86_64 -// Any additional target are added to CI should be ignored here +// Any new targets that are added to CI should be ignored here. // (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) //@ignore-target-aarch64 //@ignore-target-arm From 991e53a59766f05d5aaacf74c9b57a36f7d36265 Mon Sep 17 00:00:00 2001 From: David Carlier <devnexen@gmail.com> Date: Sat, 18 Nov 2023 19:50:20 +0000 Subject: [PATCH 04/22] libc-misc test freebsd fixes attempt --- src/tools/miri/ci.sh | 2 +- src/tools/miri/src/shims/time.rs | 4 +- .../miri/src/shims/unix/foreign_items.rs | 10 ++++ src/tools/miri/src/shims/unix/fs.rs | 9 +--- .../src/shims/unix/macos/foreign_items.rs | 7 --- .../pass-dep/shims/libc-fs-with-isolation.rs | 1 + .../miri/tests/pass-dep/shims/libc-fs.rs | 43 +++++++++++++++ .../miri/tests/pass-dep/shims/libc-misc.rs | 52 +------------------ 8 files changed, 59 insertions(+), 69 deletions(-) diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 7808c9acf93..378d7744cf2 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -108,7 +108,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests - MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc atomic env align + MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs index 4918698c6b2..611b8bc8ccc 100644 --- a/src/tools/miri/src/shims/time.rs +++ b/src/tools/miri/src/shims/time.rs @@ -31,8 +31,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let mut relative_clocks; match this.tcx.sess.target.os.as_ref() { - "linux" => { - // Linux has two main kinds of clocks. REALTIME clocks return the actual time since the + "linux" | "freebsd" => { + // Linux and FreeBSD have two main kinds of clocks. REALTIME clocks return the actual time since the // Unix epoch, including effects which may cause time to move backwards such as NTP. // Linux further distinguishes regular and "coarse" clocks, but the "coarse" version // is just specified to be "faster and less precise", so we implement both the same way. diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index d155623eb7b..7bc26788b26 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -163,6 +163,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "ftruncate64" => { let [fd, length] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let length = this.read_scalar(length)?.to_i64()?; + let result = this.ftruncate64(fd, length)?; + this.write_scalar(result, dest)?; + } + "ftruncate" => { + let [fd, length] = + this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; + let fd = this.read_scalar(fd)?.to_i32()?; + let length = this.read_target_isize(length)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 062623a7f6a..721fa161232 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1504,16 +1504,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn ftruncate64( - &mut self, - fd_op: &OpTy<'tcx, Provenance>, - length_op: &OpTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, Scalar<Provenance>> { + fn ftruncate64(&mut self, fd: i32, length: i64) -> InterpResult<'tcx, Scalar<Provenance>> { let this = self.eval_context_mut(); - let fd = this.read_scalar(fd_op)?.to_i32()?; - let length = this.read_scalar(length_op)?.to_i64()?; - // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`ftruncate64`", reject_with)?; diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index e8f35e7ba57..07e19cadd6e 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -72,13 +72,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let result = this.lseek64(fd, offset, whence)?; this.write_scalar(result, dest)?; } - "ftruncate" => { - let [fd, length] = - this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - // macOS is 64bit-only, so this is ftruncate64 - let result = this.ftruncate64(fd, length)?; - this.write_scalar(result, dest)?; - } "realpath$DARWIN_EXTSN" => { let [path, resolved_path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs index 5185db0b0e2..adfece58661 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs-with-isolation.rs @@ -1,4 +1,5 @@ //@ignore-target-windows: no libc on Windows +//@ignore-target-freebsd: FIXME needs foreign function `stat@FBSD_1.0` //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs index 767a4fdbede..697970a0885 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs @@ -23,6 +23,7 @@ fn main() { test_file_open_unix_extra_third_arg(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); + test_posix_mkstemp(); } /// Prepare: compute filename and make sure the file does not exist. @@ -151,3 +152,45 @@ fn test_o_tmpfile_flag() { .raw_os_error(), ); } + +fn test_posix_mkstemp() { + use std::ffi::OsStr; + use std::os::unix::io::FromRawFd; + use std::path::Path; + + let valid_template = "fooXXXXXX"; + // C needs to own this as `mkstemp(3)` says: + // "Since it will be modified, `template` must not be a string constant, but + // should be declared as a character array." + // There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`. + let ptr = CString::new(valid_template).unwrap().into_raw(); + let fd = unsafe { libc::mkstemp(ptr) }; + // Take ownership back in Rust to not leak memory. + let slice = unsafe { CString::from_raw(ptr) }; + assert!(fd > 0); + let osstr = OsStr::from_bytes(slice.to_bytes()); + let path: &Path = osstr.as_ref(); + let name = path.file_name().unwrap().to_string_lossy(); + assert!(name.ne("fooXXXXXX")); + assert!(name.starts_with("foo")); + assert_eq!(name.len(), 9); + assert_eq!( + name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::<Vec<char>>().len(), + 6 + ); + let file = unsafe { File::from_raw_fd(fd) }; + assert!(file.set_len(0).is_ok()); + + let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; + for t in invalid_templates { + let ptr = CString::new(t).unwrap().into_raw(); + let fd = unsafe { libc::mkstemp(ptr) }; + let _ = unsafe { CString::from_raw(ptr) }; + // "On error, -1 is returned, and errno is set to + // indicate the error" + assert_eq!(fd, -1); + let e = std::io::Error::last_os_error(); + assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); + assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput); + } +} diff --git a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs index de1acb13cbe..abb384b0a85 100644 --- a/src/tools/miri/tests/pass-dep/shims/libc-misc.rs +++ b/src/tools/miri/tests/pass-dep/shims/libc-misc.rs @@ -172,14 +172,13 @@ fn test_thread_local_errno() { } /// Tests whether clock support exists at all -#[cfg(not(target_os = "freebsd"))] fn test_clocks() { let mut tp = std::mem::MaybeUninit::<libc::timespec>::uninit(); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); let is_error = unsafe { libc::clock_gettime(libc::CLOCK_MONOTONIC, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); - #[cfg(target_os = "linux")] + #[cfg(any(target_os = "linux", target_os = "freebsd"))] { let is_error = unsafe { libc::clock_gettime(libc::CLOCK_REALTIME_COARSE, tp.as_mut_ptr()) }; assert_eq!(is_error, 0); @@ -238,51 +237,6 @@ fn test_isatty() { } } -#[cfg(not(target_os = "freebsd"))] -fn test_posix_mkstemp() { - use std::ffi::CString; - use std::ffi::OsStr; - use std::os::unix::ffi::OsStrExt; - use std::os::unix::io::FromRawFd; - use std::path::Path; - - let valid_template = "fooXXXXXX"; - // C needs to own this as `mkstemp(3)` says: - // "Since it will be modified, `template` must not be a string constant, but - // should be declared as a character array." - // There seems to be no `as_mut_ptr` on `CString` so we need to use `into_raw`. - let ptr = CString::new(valid_template).unwrap().into_raw(); - let fd = unsafe { libc::mkstemp(ptr) }; - // Take ownership back in Rust to not leak memory. - let slice = unsafe { CString::from_raw(ptr) }; - assert!(fd > 0); - let osstr = OsStr::from_bytes(slice.to_bytes()); - let path: &Path = osstr.as_ref(); - let name = path.file_name().unwrap().to_string_lossy(); - assert!(name.ne("fooXXXXXX")); - assert!(name.starts_with("foo")); - assert_eq!(name.len(), 9); - assert_eq!( - name.chars().skip(3).filter(char::is_ascii_alphanumeric).collect::<Vec<char>>().len(), - 6 - ); - let file = unsafe { File::from_raw_fd(fd) }; - assert!(file.set_len(0).is_ok()); - - let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; - for t in invalid_templates { - let ptr = CString::new(t).unwrap().into_raw(); - let fd = unsafe { libc::mkstemp(ptr) }; - let _ = unsafe { CString::from_raw(ptr) }; - // "On error, -1 is returned, and errno is set to - // indicate the error" - assert_eq!(fd, -1); - let e = std::io::Error::last_os_error(); - assert_eq!(e.raw_os_error(), Some(libc::EINVAL)); - assert_eq!(e.kind(), std::io::ErrorKind::InvalidInput); - } -} - fn test_memcpy() { unsafe { let src = [1i8, 2, 3]; @@ -406,9 +360,6 @@ fn test_reallocarray() { fn main() { test_posix_gettimeofday(); - #[cfg(not(target_os = "freebsd"))] // FIXME we should support this on FreeBSD as well - test_posix_mkstemp(); - test_posix_realpath_alloc(); test_posix_realpath_noalloc(); test_posix_realpath_errors(); @@ -417,7 +368,6 @@ fn main() { test_isatty(); - #[cfg(not(target_os = "freebsd"))] // FIXME we should support this on FreeBSD as well test_clocks(); test_dlsym(); From 81303e7ea5209dbfbdf359b9311681d4151c4c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io> Date: Sat, 18 Nov 2023 19:39:51 +0100 Subject: [PATCH 05/22] Implement all 16 AVX compare operators `_mm_cmp_{ss,ps,sd,pd}` functions are AVX functions that use `llvm.x86.sse{,2}` prefixed intrinsics, so they were "accidentally" partially implemented when SSE and SSE2 intrinsics were implemented. The 16 AVX compare operators are now implemented and tested. --- src/tools/miri/src/shims/x86/mod.rs | 120 +++++++------ src/tools/miri/src/shims/x86/sse.rs | 22 ++- src/tools/miri/src/shims/x86/sse2.rs | 20 ++- .../miri/tests/pass/intrinsics-x86-avx.rs | 162 ++++++++++++++++++ 4 files changed, 257 insertions(+), 67 deletions(-) create mode 100644 src/tools/miri/tests/pass/intrinsics-x86-avx.rs diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index d88a3127ecc..2a2171134d4 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -119,53 +119,32 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: } } -/// Floating point comparison operation -/// -/// <https://www.felixcloutier.com/x86/cmpss> -/// <https://www.felixcloutier.com/x86/cmpps> -/// <https://www.felixcloutier.com/x86/cmpsd> -/// <https://www.felixcloutier.com/x86/cmppd> -#[derive(Copy, Clone)] -enum FloatCmpOp { - Eq, - Lt, - Le, - Unord, - Neq, - /// Not less-than - Nlt, - /// Not less-or-equal - Nle, - /// Ordered, i.e. neither of them is NaN - Ord, -} - -impl FloatCmpOp { - /// Convert from the `imm` argument used to specify the comparison - /// operation in intrinsics such as `llvm.x86.sse.cmp.ss`. - fn from_intrinsic_imm(imm: i8, intrinsic: &str) -> InterpResult<'_, Self> { - match imm { - 0 => Ok(Self::Eq), - 1 => Ok(Self::Lt), - 2 => Ok(Self::Le), - 3 => Ok(Self::Unord), - 4 => Ok(Self::Neq), - 5 => Ok(Self::Nlt), - 6 => Ok(Self::Nle), - 7 => Ok(Self::Ord), - imm => { - throw_unsup_format!("invalid `imm` parameter of {intrinsic}: {imm}"); - } - } - } -} - #[derive(Copy, Clone)] enum FloatBinOp { /// Arithmetic operation Arith(mir::BinOp), /// Comparison - Cmp(FloatCmpOp), + /// + /// The semantics of this operator is a case distinction: we compare the two operands, + /// and then we return one of the four booleans `gt`, `lt`, `eq`, `unord` depending on + /// which class they fall into. + /// + /// AVX supports all 16 combinations, SSE only a subset + /// + /// <https://www.felixcloutier.com/x86/cmpss> + /// <https://www.felixcloutier.com/x86/cmpps> + /// <https://www.felixcloutier.com/x86/cmpsd> + /// <https://www.felixcloutier.com/x86/cmppd> + Cmp { + /// Result when lhs < rhs + gt: bool, + /// Result when lhs > rhs + lt: bool, + /// Result when lhs == rhs + eq: bool, + /// Result when lhs is NaN or rhs is NaN + unord: bool, + }, /// Minimum value (with SSE semantics) /// /// <https://www.felixcloutier.com/x86/minss> @@ -182,6 +161,44 @@ enum FloatBinOp { Max, } +impl FloatBinOp { + /// Convert from the `imm` argument used to specify the comparison + /// operation in intrinsics such as `llvm.x86.sse.cmp.ss`. + fn cmp_from_imm(imm: i8, intrinsic: &str) -> InterpResult<'_, Self> { + // Only bits 0..=4 are used, remaining should be zero. + if imm & !0b1_1111 != 0 { + throw_unsup_format!("invalid `imm` parameter of {intrinsic}: 0x{imm:x}"); + } + // Bit 4 specifies whether the operation is quiet or signaling, which + // we do not care in Miri. + // Bits 0..=2 specifies the operation. + // `gt` indicates the result to be returned when the LHS is strictly + // greater than the RHS, and so on. + let (gt, lt, eq, unord) = match imm & 0b111 { + // Equal + 0x0 => (false, false, true, false), + // Less-than + 0x1 => (false, true, false, false), + // Less-or-equal + 0x2 => (false, true, true, false), + // Unordered (either is NaN) + 0x3 => (false, false, false, true), + // Not equal + 0x4 => (true, true, false, true), + // Not less-than + 0x5 => (true, false, true, true), + // Not less-or-equal + 0x6 => (true, false, false, true), + // Ordered (neither is NaN) + 0x7 => (true, true, true, false), + _ => unreachable!(), + }; + // When bit 3 is 1 (only possible in AVX), unord is toggled. + let unord = unord ^ (imm & 0b1000 != 0); + Ok(Self::Cmp { gt, lt, eq, unord }) + } +} + /// Performs `which` scalar operation on `left` and `right` and returns /// the result. fn bin_op_float<'tcx, F: rustc_apfloat::Float>( @@ -195,20 +212,15 @@ fn bin_op_float<'tcx, F: rustc_apfloat::Float>( let res = this.wrapping_binary_op(which, left, right)?; Ok(res.to_scalar()) } - FloatBinOp::Cmp(which) => { + FloatBinOp::Cmp { gt, lt, eq, unord } => { let left = left.to_scalar().to_float::<F>()?; let right = right.to_scalar().to_float::<F>()?; - // FIXME: Make sure that these operations match the semantics - // of cmpps/cmpss/cmppd/cmpsd - let res = match which { - FloatCmpOp::Eq => left == right, - FloatCmpOp::Lt => left < right, - FloatCmpOp::Le => left <= right, - FloatCmpOp::Unord => left.is_nan() || right.is_nan(), - FloatCmpOp::Neq => left != right, - FloatCmpOp::Nlt => !(left < right), - FloatCmpOp::Nle => !(left <= right), - FloatCmpOp::Ord => !left.is_nan() && !right.is_nan(), + + let res = match left.partial_cmp(&right) { + None => unord, + Some(std::cmp::Ordering::Less) => lt, + Some(std::cmp::Ordering::Equal) => eq, + Some(std::cmp::Ordering::Greater) => gt, }; Ok(bool_to_simd_element(res, Size::from_bits(F::BITS))) } diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 831228b7a26..e15023c3c21 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -5,7 +5,7 @@ use rustc_target::spec::abi::Abi; use rand::Rng as _; -use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; +use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp}; use crate::*; use shims::foreign_items::EmulateForeignItemResult; @@ -95,33 +95,41 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: unary_op_ps(this, which, op, dest)?; } - // Used to implement the _mm_cmp_ss function. + // Used to implement the _mm_cmp*_ss functions. // Performs a comparison operation on the first component of `left` // and `right`, returning 0 if false or `u32::MAX` if true. The remaining // components are copied from `left`. + // _mm_cmp_ss is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ss are SSE functions + // with hard-coded operations. "cmp.ss" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( + let which = FloatBinOp::cmp_from_imm( this.read_scalar(imm)?.to_i8()?, "llvm.x86.sse.cmp.ss", - )?); + )?; bin_op_simd_float_first::<Single>(this, which, left, right, dest)?; } - // Used to implement the _mm_cmp_ps function. + // Used to implement the _mm_cmp*_ps functions. // Performs a comparison operation on each component of `left` // and `right`. For each component, returns 0 if false or u32::MAX // if true. + // _mm_cmp_ps is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_ps are SSE functions + // with hard-coded operations. "cmp.ps" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( + let which = FloatBinOp::cmp_from_imm( this.read_scalar(imm)?.to_i8()?, "llvm.x86.sse.cmp.ps", - )?); + )?; bin_op_simd_float_all::<Single>(this, which, left, right, dest)?; } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 3f2b9f5f0ad..55520771cf6 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::spec::abi::Abi; -use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp, FloatCmpOp}; +use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp}; use crate::*; use shims::foreign_items::EmulateForeignItemResult; @@ -461,18 +461,22 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(res, &dest)?; } } - // Used to implement the _mm_cmp*_sd function. + // Used to implement the _mm_cmp*_sd functions. // Performs a comparison operation on the first component of `left` // and `right`, returning 0 if false or `u64::MAX` if true. The remaining // components are copied from `left`. + // _mm_cmp_sd is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_sd are SSE2 functions + // with hard-coded operations. "cmp.sd" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( + let which = FloatBinOp::cmp_from_imm( this.read_scalar(imm)?.to_i8()?, "llvm.x86.sse2.cmp.sd", - )?); + )?; bin_op_simd_float_first::<Double>(this, which, left, right, dest)?; } @@ -480,14 +484,18 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: // Performs a comparison operation on each component of `left` // and `right`. For each component, returns 0 if false or `u64::MAX` // if true. + // _mm_cmp_pd is actually an AVX function where the operation is specified + // by a const parameter. + // _mm_cmp{eq,lt,le,gt,ge,neq,nlt,nle,ngt,nge,ord,unord}_pd are SSE2 functions + // with hard-coded operations. "cmp.pd" => { let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::Cmp(FloatCmpOp::from_intrinsic_imm( + let which = FloatBinOp::cmp_from_imm( this.read_scalar(imm)?.to_i8()?, "llvm.x86.sse2.cmp.pd", - )?); + )?; bin_op_simd_float_all::<Double>(this, which, left, right, dest)?; } diff --git a/src/tools/miri/tests/pass/intrinsics-x86-avx.rs b/src/tools/miri/tests/pass/intrinsics-x86-avx.rs new file mode 100644 index 00000000000..933e3d4153a --- /dev/null +++ b/src/tools/miri/tests/pass/intrinsics-x86-avx.rs @@ -0,0 +1,162 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// (We cannot use `cfg`-based tricks here since the `target-feature` flags below only work on x86.) +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +//@compile-flags: -C target-feature=+avx + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; +use std::mem::transmute; + +fn main() { + assert!(is_x86_feature_detected!("avx")); + + unsafe { + test_avx(); + } +} + +#[target_feature(enable = "avx")] +unsafe fn test_avx() { + fn expected_cmp<F: PartialOrd>(imm: i32, lhs: F, rhs: F, if_t: F, if_f: F) -> F { + let res = match imm { + _CMP_EQ_OQ => lhs == rhs, + _CMP_LT_OS => lhs < rhs, + _CMP_LE_OS => lhs <= rhs, + _CMP_UNORD_Q => lhs.partial_cmp(&rhs).is_none(), + _CMP_NEQ_UQ => lhs != rhs, + _CMP_NLT_UQ => !(lhs < rhs), + _CMP_NLE_UQ => !(lhs <= rhs), + _CMP_ORD_Q => lhs.partial_cmp(&rhs).is_some(), + _CMP_EQ_UQ => lhs == rhs || lhs.partial_cmp(&rhs).is_none(), + _CMP_NGE_US => !(lhs >= rhs), + _CMP_NGT_US => !(lhs > rhs), + _CMP_FALSE_OQ => false, + _CMP_NEQ_OQ => lhs != rhs && lhs.partial_cmp(&rhs).is_some(), + _CMP_GE_OS => lhs >= rhs, + _CMP_GT_OS => lhs > rhs, + _CMP_TRUE_US => true, + _ => unreachable!(), + }; + if res { if_t } else { if_f } + } + fn expected_cmp_f32(imm: i32, lhs: f32, rhs: f32) -> f32 { + expected_cmp(imm, lhs, rhs, f32::from_bits(u32::MAX), 0.0) + } + fn expected_cmp_f64(imm: i32, lhs: f64, rhs: f64) -> f64 { + expected_cmp(imm, lhs, rhs, f64::from_bits(u64::MAX), 0.0) + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_ss<const IMM: i32>() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f32::NAN, 0.0), + (0.0, f32::NAN), + (f32::NAN, f32::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_setr_ps(lhs, 2.0, 3.0, 4.0); + let b = _mm_setr_ps(rhs, 5.0, 6.0, 7.0); + let r: [u32; 4] = transmute(_mm_cmp_ss::<IMM>(a, b)); + let e: [u32; 4] = + transmute(_mm_setr_ps(expected_cmp_f32(IMM, lhs, rhs), 2.0, 3.0, 4.0)); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_ps<const IMM: i32>() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f32::NAN, 0.0), + (0.0, f32::NAN), + (f32::NAN, f32::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_set1_ps(lhs); + let b = _mm_set1_ps(rhs); + let r: [u32; 4] = transmute(_mm_cmp_ps::<IMM>(a, b)); + let e: [u32; 4] = transmute(_mm_set1_ps(expected_cmp_f32(IMM, lhs, rhs))); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_sd<const IMM: i32>() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f64::NAN, 0.0), + (0.0, f64::NAN), + (f64::NAN, f64::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_setr_pd(lhs, 2.0); + let b = _mm_setr_pd(rhs, 3.0); + let r: [u64; 2] = transmute(_mm_cmp_sd::<IMM>(a, b)); + let e: [u64; 2] = transmute(_mm_setr_pd(expected_cmp_f64(IMM, lhs, rhs), 2.0)); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_mm_cmp_pd<const IMM: i32>() { + let values = [ + (1.0, 1.0), + (0.0, 1.0), + (1.0, 0.0), + (f64::NAN, 0.0), + (0.0, f64::NAN), + (f64::NAN, f64::NAN), + ]; + + for (lhs, rhs) in values { + let a = _mm_set1_pd(lhs); + let b = _mm_set1_pd(rhs); + let r: [u64; 2] = transmute(_mm_cmp_pd::<IMM>(a, b)); + let e: [u64; 2] = transmute(_mm_set1_pd(expected_cmp_f64(IMM, lhs, rhs))); + assert_eq!(r, e); + } + } + + #[target_feature(enable = "avx")] + unsafe fn test_cmp<const IMM: i32>() { + test_mm_cmp_ss::<IMM>(); + test_mm_cmp_ps::<IMM>(); + test_mm_cmp_sd::<IMM>(); + test_mm_cmp_pd::<IMM>(); + } + + test_cmp::<_CMP_EQ_OQ>(); + test_cmp::<_CMP_LT_OS>(); + test_cmp::<_CMP_LE_OS>(); + test_cmp::<_CMP_UNORD_Q>(); + test_cmp::<_CMP_NEQ_UQ>(); + test_cmp::<_CMP_NLT_UQ>(); + test_cmp::<_CMP_NLE_UQ>(); + test_cmp::<_CMP_ORD_Q>(); + test_cmp::<_CMP_EQ_UQ>(); + test_cmp::<_CMP_NGE_US>(); + test_cmp::<_CMP_NGT_US>(); + test_cmp::<_CMP_FALSE_OQ>(); + test_cmp::<_CMP_NEQ_OQ>(); + test_cmp::<_CMP_GE_OS>(); + test_cmp::<_CMP_GT_OS>(); + test_cmp::<_CMP_TRUE_US>(); +} From 9007cc484bdff639d3c8ab1304e6dd4257589f82 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 21 Nov 2023 18:23:22 +0100 Subject: [PATCH 06/22] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2a19781775b..00a41008d3b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -820f06b21f8373060ff7b515715b8440a6a6c197 +0ff861096449f47956521b40e5e4e88caa7fe27c From f1b944d1a2364f4baf4d1d9ce421fc4126adc6f5 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Tue, 21 Nov 2023 18:24:57 +0100 Subject: [PATCH 07/22] fmt --- src/tools/miri/src/lib.rs | 2 +- src/tools/miri/src/provenance_gc.rs | 9 ++------- src/tools/miri/tests/utils/mod.rs | 4 +--- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 119ec555b2e..70e9c443e90 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -125,7 +125,7 @@ pub use crate::machine::{ }; pub use crate::mono_hash_map::MonoHashMap; pub use crate::operator::EvalContextExt as _; -pub use crate::provenance_gc::{EvalContextExt as _, VisitProvenance, VisitWith, LiveAllocs}; +pub use crate::provenance_gc::{EvalContextExt as _, LiveAllocs, VisitProvenance, VisitWith}; pub use crate::range_map::RangeMap; /// Insert rustc arguments at the beginning of the argument list that Miri wants to be diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index eac4aad27a0..4456e641b00 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -157,15 +157,13 @@ pub struct LiveAllocs<'a, 'mir, 'tcx> { impl LiveAllocs<'_, '_, '_> { pub fn is_live(&self, id: AllocId) -> bool { - self.collected.contains(&id) || - self.ecx.is_alloc_live(id) + self.collected.contains(&id) || self.ecx.is_alloc_live(id) } } impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn run_provenance_gc(&mut self) { - // We collect all tags from various parts of the interpreter, but also let this = self.eval_context_mut(); @@ -196,10 +194,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn remove_unreachable_allocs(&mut self, allocs: FxHashSet<AllocId>) { let this = self.eval_context_ref(); - let allocs = LiveAllocs { - ecx: this, - collected: allocs, - }; + let allocs = LiveAllocs { ecx: this, collected: allocs }; this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); if let Some(borrow_tracker) = &this.machine.borrow_tracker { diff --git a/src/tools/miri/tests/utils/mod.rs b/src/tools/miri/tests/utils/mod.rs index 6386162e095..3b817667f13 100644 --- a/src/tools/miri/tests/utils/mod.rs +++ b/src/tools/miri/tests/utils/mod.rs @@ -12,7 +12,5 @@ pub use miri_extern::*; pub fn run_provenance_gc() { // SAFETY: No preconditions. The GC is fine to run at any time. - unsafe { - miri_run_provenance_gc() - } + unsafe { miri_run_provenance_gc() } } From 09358a05c37abd9a9a6b31a9c53d2378f8ab9d6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io> Date: Mon, 20 Nov 2023 19:29:02 +0100 Subject: [PATCH 08/22] Check that target features required by LLVM intrinsics are enabled --- src/tools/miri/src/helpers.rs | 18 ++++++++ src/tools/miri/src/shims/foreign_items.rs | 2 + src/tools/miri/src/shims/x86/aesni.rs | 1 + src/tools/miri/src/shims/x86/mod.rs | 13 ++++-- src/tools/miri/src/shims/x86/sse.rs | 13 +++--- src/tools/miri/src/shims/x86/sse2.rs | 13 +++--- src/tools/miri/src/shims/x86/sse3.rs | 1 + src/tools/miri/src/shims/x86/sse41.rs | 1 + src/tools/miri/src/shims/x86/ssse3.rs | 1 + .../fail/shims/intrinsic_target_feature.rs | 42 +++++++++++++++++++ .../shims/intrinsic_target_feature.stderr | 15 +++++++ 11 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs create mode 100644 src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 965cd534d1e..22f6e99f545 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1063,6 +1063,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => span_bug!(this.cur_span(), "unexpected type: {ty:?}"), } } + + /// Checks that target feature `target_feature` is enabled. + /// + /// If not enabled, emits an UB error that states that the feature is + /// required by `intrinsic`. + fn expect_target_feature_for_intrinsic( + &self, + intrinsic: Symbol, + target_feature: &str, + ) -> InterpResult<'tcx, ()> { + let this = self.eval_context_ref(); + if !this.tcx.sess.unstable_target_features.contains(&Symbol::intern(target_feature)) { + throw_ub_format!( + "attempted to call intrinsic `{intrinsic}` that requires missing target feature {target_feature}" + ); + } + Ok(()) + } } impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> { diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 2d5df303745..746f874275d 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -1008,9 +1008,11 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { "llvm.arm.hint" if this.tcx.sess.target.arch == "arm" => { let [arg] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?; let arg = this.read_scalar(arg)?.to_i32()?; + // Note that different arguments might have different target feature requirements. match arg { // YIELD 1 => { + this.expect_target_feature_for_intrinsic(link_name, "v6")?; this.yield_active_thread(); } _ => { diff --git a/src/tools/miri/src/shims/x86/aesni.rs b/src/tools/miri/src/shims/x86/aesni.rs index aef930595b2..fb0b7015127 100644 --- a/src/tools/miri/src/shims/x86/aesni.rs +++ b/src/tools/miri/src/shims/x86/aesni.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "aes")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.aesni.").unwrap(); diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 2a2171134d4..78590b08933 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -164,7 +164,11 @@ enum FloatBinOp { impl FloatBinOp { /// Convert from the `imm` argument used to specify the comparison /// operation in intrinsics such as `llvm.x86.sse.cmp.ss`. - fn cmp_from_imm(imm: i8, intrinsic: &str) -> InterpResult<'_, Self> { + fn cmp_from_imm<'tcx>( + this: &crate::MiriInterpCx<'_, 'tcx>, + imm: i8, + intrinsic: Symbol, + ) -> InterpResult<'tcx, Self> { // Only bits 0..=4 are used, remaining should be zero. if imm & !0b1_1111 != 0 { throw_unsup_format!("invalid `imm` parameter of {intrinsic}: 0x{imm:x}"); @@ -174,7 +178,7 @@ impl FloatBinOp { // Bits 0..=2 specifies the operation. // `gt` indicates the result to be returned when the LHS is strictly // greater than the RHS, and so on. - let (gt, lt, eq, unord) = match imm & 0b111 { + let (gt, lt, eq, mut unord) = match imm & 0b111 { // Equal 0x0 => (false, false, true, false), // Less-than @@ -194,7 +198,10 @@ impl FloatBinOp { _ => unreachable!(), }; // When bit 3 is 1 (only possible in AVX), unord is toggled. - let unord = unord ^ (imm & 0b1000 != 0); + if imm & 0b1000 != 0 { + this.expect_target_feature_for_intrinsic(intrinsic, "avx")?; + unord = !unord; + } Ok(Self::Cmp { gt, lt, eq, unord }) } } diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index e15023c3c21..8cdb3402f0c 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -21,6 +21,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse.").unwrap(); // All these intrinsics operate on 128-bit (f32x4) SIMD vectors unless stated otherwise. @@ -107,10 +108,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::cmp_from_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse.cmp.ss", - )?; + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_first::<Single>(this, which, left, right, dest)?; } @@ -126,10 +125,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::cmp_from_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse.cmp.ps", - )?; + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_all::<Single>(this, which, left, right, dest)?; } diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 55520771cf6..01496b319f1 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -20,6 +20,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse2")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse2.").unwrap(); @@ -473,10 +474,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::cmp_from_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse2.cmp.sd", - )?; + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_first::<Double>(this, which, left, right, dest)?; } @@ -492,10 +491,8 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [left, right, imm] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let which = FloatBinOp::cmp_from_imm( - this.read_scalar(imm)?.to_i8()?, - "llvm.x86.sse2.cmp.pd", - )?; + let which = + FloatBinOp::cmp_from_imm(this, this.read_scalar(imm)?.to_i8()?, link_name)?; bin_op_simd_float_all::<Double>(this, which, left, right, dest)?; } diff --git a/src/tools/miri/src/shims/x86/sse3.rs b/src/tools/miri/src/shims/x86/sse3.rs index 270da36f0e3..99a7a4f2f88 100644 --- a/src/tools/miri/src/shims/x86/sse3.rs +++ b/src/tools/miri/src/shims/x86/sse3.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse3")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse3.").unwrap(); diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index 523f3bfc26f..d9bccecb497 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "sse4.1")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.sse41.").unwrap(); diff --git a/src/tools/miri/src/shims/x86/ssse3.rs b/src/tools/miri/src/shims/x86/ssse3.rs index dbc2b947b33..724150fd2fe 100644 --- a/src/tools/miri/src/shims/x86/ssse3.rs +++ b/src/tools/miri/src/shims/x86/ssse3.rs @@ -18,6 +18,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: dest: &PlaceTy<'tcx, Provenance>, ) -> InterpResult<'tcx, EmulateForeignItemResult> { let this = self.eval_context_mut(); + this.expect_target_feature_for_intrinsic(link_name, "ssse3")?; // Prefix should have already been checked. let unprefixed_name = link_name.as_str().strip_prefix("llvm.x86.ssse3.").unwrap(); diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs new file mode 100644 index 00000000000..9263ad381d1 --- /dev/null +++ b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.rs @@ -0,0 +1,42 @@ +// Ignore everything except x86 and x86_64 +// Any new targets that are added to CI should be ignored here. +// We cannot use `cfg`-based tricks here since the output would be +// different for non-x86 targets. +//@ignore-target-aarch64 +//@ignore-target-arm +//@ignore-target-avr +//@ignore-target-s390x +//@ignore-target-thumbv7em +//@ignore-target-wasm32 +// Explicitly disable SSE4.1 because it is enabled by default on macOS +//@compile-flags: -C target-feature=-sse4.1 + +#![feature(link_llvm_intrinsics, simd_ffi)] + +#[cfg(target_arch = "x86")] +use std::arch::x86::*; +#[cfg(target_arch = "x86_64")] +use std::arch::x86_64::*; + +fn main() { + assert!(is_x86_feature_detected!("sse")); + assert!(!is_x86_feature_detected!("sse4.1")); + + unsafe { + // Pass, since SSE is enabled + addss(_mm_setzero_ps(), _mm_setzero_ps()); + + // Fail, since SSE4.1 is not enabled + dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0); + //~^ ERROR: Undefined Behavior: attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1 + } +} + +#[allow(improper_ctypes)] +extern "C" { + #[link_name = "llvm.x86.sse.add.ss"] + fn addss(a: __m128, b: __m128) -> __m128; + + #[link_name = "llvm.x86.sse41.dpps"] + fn dpps(a: __m128, b: __m128, imm8: u8) -> __m128; +} diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr new file mode 100644 index 00000000000..c034261338a --- /dev/null +++ b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1 + --> $DIR/intrinsic_target_feature.rs:LL:CC + | +LL | dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempted to call intrinsic `llvm.x86.sse41.dpps` that requires missing target feature sse4.1 + | + = 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/intrinsic_target_feature.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + From 804afa4a94f4e9a502531c19c9a150eb1d33f4f6 Mon Sep 17 00:00:00 2001 From: The Miri Conjob Bot <miri@cron.bot> Date: Thu, 23 Nov 2023 04:55:03 +0000 Subject: [PATCH 09/22] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 00a41008d3b..ee27d8ed9a8 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0ff861096449f47956521b40e5e4e88caa7fe27c +360bafad68cfea2682cf016070e533c45a00150f From 4896c953e18869c57c10cea3aceb81d56537e504 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Thu, 23 Nov 2023 08:14:50 +0100 Subject: [PATCH 10/22] detect and test for data races between setenv and getenv --- src/tools/miri/src/helpers.rs | 15 ++---- src/tools/miri/src/shims/env.rs | 53 ++++++++++++------- src/tools/miri/src/shims/foreign_items.rs | 3 +- .../src/shims/unix/android/foreign_items.rs | 2 +- .../fail-dep/shims/env-set_var-data-race.rs | 17 ++++++ .../shims/env-set_var-data-race.stderr | 20 +++++++ .../pass-dep/shims/env-cleanup-data-race.rs | 5 +- 7 files changed, 79 insertions(+), 36 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs create mode 100644 src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 965cd534d1e..f3890fc1dcb 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -565,10 +565,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { /// is part of the UNIX family. It panics showing a message with the `name` of the foreign function /// if this is not the case. fn assert_target_os_is_unix(&self, name: &str) { - assert!( - target_os_is_unix(self.eval_context_ref().tcx.sess.target.os.as_ref()), - "`{name}` is only available for supported UNIX family targets", - ); + assert!(self.target_os_is_unix(), "`{name}` is only available for unix targets",); + } + + fn target_os_is_unix(&self) -> bool { + self.eval_context_ref().tcx.sess.target.families.iter().any(|f| f == "unix") } /// Get last error variable as a place, lazily allocating thread-local storage for it if @@ -1143,12 +1144,6 @@ pub fn get_local_crates(tcx: TyCtxt<'_>) -> Vec<CrateNum> { local_crates } -/// Helper function used inside the shims of foreign functions to check that -/// `target_os` is a supported UNIX OS. -pub fn target_os_is_unix(target_os: &str) -> bool { - matches!(target_os, "linux" | "macos" | "freebsd" | "android") -} - pub(crate) fn bool_to_simd_element(b: bool, size: Size) -> Scalar<Provenance> { // SIMD uses all-1 as pattern for "true". In two's complement, // -1 has all its bits set to one and `from_int` will truncate or diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs index 42438985907..9e19f720211 100644 --- a/src/tools/miri/src/shims/env.rs +++ b/src/tools/miri/src/shims/env.rs @@ -9,7 +9,6 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::Ty; use rustc_target::abi::Size; -use crate::helpers::target_os_is_unix; use crate::*; /// Check whether an operation that writes to a target buffer was successful. @@ -53,16 +52,15 @@ impl<'tcx> EnvVars<'tcx> { ecx: &mut InterpCx<'mir, 'tcx, MiriMachine<'mir, 'tcx>>, config: &MiriConfig, ) -> InterpResult<'tcx> { - let target_os = ecx.tcx.sess.target.os.as_ref(); - + // Initialize the `env_vars` map. // Skip the loop entirely if we don't want to forward anything. if ecx.machine.communicate() || !config.forwarded_env_vars.is_empty() { for (name, value) in &config.env { let forward = ecx.machine.communicate() || config.forwarded_env_vars.iter().any(|v| **v == *name); if forward { - let var_ptr = match target_os { - target if target_os_is_unix(target) => + let var_ptr = match ecx.tcx.sess.target.os.as_ref() { + _ if ecx.target_os_is_unix() => alloc_env_var_as_c_str(name.as_ref(), value.as_ref(), ecx)?, "windows" => alloc_env_var_as_wide_str(name.as_ref(), value.as_ref(), ecx)?, unsupported => @@ -75,7 +73,17 @@ impl<'tcx> EnvVars<'tcx> { } } } - ecx.update_environ() + + // Initialize the `environ` pointer when needed. + if ecx.target_os_is_unix() { + // This is memory backing an extern static, hence `ExternStatic`, not `Env`. + let layout = ecx.machine.layouts.mut_raw_ptr; + let place = ecx.allocate(layout, MiriMemoryKind::ExternStatic.into())?; + ecx.write_null(&place)?; + ecx.machine.env_vars.environ = Some(place); + ecx.update_environ()?; + } + Ok(()) } pub(crate) fn cleanup<'mir>( @@ -87,9 +95,11 @@ impl<'tcx> EnvVars<'tcx> { ecx.deallocate_ptr(ptr, None, MiriMemoryKind::Runtime.into())?; } // Deallocate environ var list. - let environ = ecx.machine.env_vars.environ.as_ref().unwrap(); - let old_vars_ptr = ecx.read_pointer(environ)?; - ecx.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?; + if ecx.target_os_is_unix() { + let environ = ecx.machine.env_vars.environ.as_ref().unwrap(); + let old_vars_ptr = ecx.read_pointer(environ)?; + ecx.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?; + } Ok(()) } } @@ -127,6 +137,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let name_ptr = this.read_pointer(name_op)?; let name = this.read_os_str_from_c_str(name_ptr)?; + this.read_environ()?; Ok(match this.machine.env_vars.map.get(name) { Some(var_ptr) => { // The offset is used to strip the "{name}=" part of the string. @@ -275,7 +286,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Delete environment variable `{name}` if let Some(var) = this.machine.env_vars.map.remove(&name) { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; - this.update_environ()?; } Ok(this.eval_windows("c", "TRUE")) } else { @@ -284,7 +294,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { if let Some(var) = this.machine.env_vars.map.insert(name, var_ptr) { this.deallocate_ptr(var, None, MiriMemoryKind::Runtime.into())?; } - this.update_environ()?; Ok(this.eval_windows("c", "TRUE")) } } @@ -431,15 +440,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { fn update_environ(&mut self) -> InterpResult<'tcx> { let this = self.eval_context_mut(); // Deallocate the old environ list, if any. - if let Some(environ) = this.machine.env_vars.environ.as_ref() { - let old_vars_ptr = this.read_pointer(environ)?; + let environ = this.machine.env_vars.environ.as_ref().unwrap().clone(); + let old_vars_ptr = this.read_pointer(&environ)?; + if !this.ptr_is_null(old_vars_ptr)? { this.deallocate_ptr(old_vars_ptr, None, MiriMemoryKind::Runtime.into())?; - } else { - // No `environ` allocated yet, let's do that. - // This is memory backing an extern static, hence `ExternStatic`, not `Env`. - let layout = this.machine.layouts.mut_raw_ptr; - let place = this.allocate(layout, MiriMemoryKind::ExternStatic.into())?; - this.machine.env_vars.environ = Some(place); } // Collect all the pointers to each variable in a vector. @@ -459,11 +463,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let place = this.project_field(&vars_place, idx)?; this.write_pointer(var, &place)?; } - this.write_pointer(vars_place.ptr(), &this.machine.env_vars.environ.clone().unwrap())?; + this.write_pointer(vars_place.ptr(), &environ)?; Ok(()) } + /// Reads from the `environ` static. + /// We don't actually care about the result, but we care about this potentially causing a data race. + fn read_environ(&self) -> InterpResult<'tcx> { + let this = self.eval_context_ref(); + let environ = this.machine.env_vars.environ.as_ref().unwrap(); + let _vars_ptr = this.read_pointer(environ)?; + Ok(()) + } + fn getpid(&mut self) -> InterpResult<'tcx, i32> { let this = self.eval_context_mut(); this.assert_target_os_is_unix("getpid"); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index d7aaa08dbf3..6443efd7bde 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -22,7 +22,6 @@ use rustc_target::{ }; use super::backtrace::EvalContextExt as _; -use crate::helpers::target_os_is_unix; use crate::*; /// Type of dynamic symbols (for `dlsym` et al) @@ -1058,7 +1057,7 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { // Platform-specific shims _ => return match this.tcx.sess.target.os.as_ref() { - target_os if target_os_is_unix(target_os) => + _ if this.target_os_is_unix() => shims::unix::foreign_items::EvalContextExt::emulate_foreign_item_inner( this, link_name, abi, args, dest, ), diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs index f61ebd5a3a8..5653e3f1129 100644 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/android/foreign_items.rs @@ -11,7 +11,7 @@ pub fn is_dyn_sym(_name: &str) -> bool { } pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - #[allow(unused, clippy::match_single_binding)] // there isn't anything here yet + #[allow(unused, clippy::match_single_binding)] // FIXME: there isn't anything here yet fn emulate_foreign_item_inner( &mut self, link_name: Symbol, diff --git a/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs new file mode 100644 index 00000000000..2b9e7a34d65 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.rs @@ -0,0 +1,17 @@ +//@compile-flags: -Zmiri-disable-isolation -Zmiri-preemption-rate=0 +//@ignore-target-windows: No libc on Windows + +use std::env; +use std::thread; + +fn main() { + let t = thread::spawn(|| unsafe { + // Access the environment in another thread without taking the env lock. + // This represents some C code that queries the environment. + libc::getenv(b"TZ\0".as_ptr().cast()); //~ERROR: Data race detected + }); + // Meanwhile, the main thread uses the "safe" Rust env accessor. + env::set_var("MY_RUST_VAR", "Ferris"); + + t.join().unwrap(); +} diff --git a/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr new file mode 100644 index 00000000000..a202d7c6844 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr @@ -0,0 +1,20 @@ +error: Undefined Behavior: Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here + --> $DIR/env-set_var-data-race.rs:LL:CC + | +LL | libc::getenv(b"TZ/0".as_ptr().cast()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Data race detected between (1) non-atomic write on thread `main` and (2) non-atomic read on thread `<unnamed>` at ALLOC. (2) just happened here + | +help: and (1) occurred earlier here + --> $DIR/env-set_var-data-race.rs:LL:CC + | +LL | env::set_var("MY_RUST_VAR", "Ferris"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = 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 (of the first span): + = note: inside closure at $DIR/env-set_var-data-race.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to previous error + diff --git a/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs b/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs index d36ffe70321..5c29a1b15a7 100644 --- a/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs +++ b/src/tools/miri/tests/pass-dep/shims/env-cleanup-data-race.rs @@ -2,15 +2,13 @@ //@ignore-target-windows: No libc on Windows use std::ffi::CStr; -use std::ffi::CString; use std::thread; fn main() { unsafe { thread::spawn(|| { // Access the environment in another thread without taking the env lock - let k = CString::new("MIRI_ENV_VAR_TEST".as_bytes()).unwrap(); - let s = libc::getenv(k.as_ptr()) as *const libc::c_char; + let s = libc::getenv("MIRI_ENV_VAR_TEST\0".as_ptr().cast()); if s.is_null() { panic!("null"); } @@ -19,5 +17,6 @@ fn main() { thread::yield_now(); // After the main thread exits, env vars will be cleaned up -- but because we have not *joined* // the other thread, those accesses technically race with those in the other thread. + // We don't want to emit an error here, though. } } From 4b69e525f5e090d1268cbace2846a8985dce6fae Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Thu, 23 Nov 2023 08:19:01 +0100 Subject: [PATCH 11/22] remove stub android files that don't do anything --- .../src/shims/unix/android/foreign_items.rs | 30 ------------------- src/tools/miri/src/shims/unix/android/mod.rs | 1 - .../miri/src/shims/unix/foreign_items.rs | 5 +--- src/tools/miri/src/shims/unix/mod.rs | 1 - 4 files changed, 1 insertion(+), 36 deletions(-) delete mode 100644 src/tools/miri/src/shims/unix/android/foreign_items.rs delete mode 100644 src/tools/miri/src/shims/unix/android/mod.rs diff --git a/src/tools/miri/src/shims/unix/android/foreign_items.rs b/src/tools/miri/src/shims/unix/android/foreign_items.rs deleted file mode 100644 index 5653e3f1129..00000000000 --- a/src/tools/miri/src/shims/unix/android/foreign_items.rs +++ /dev/null @@ -1,30 +0,0 @@ -use rustc_span::Symbol; -use rustc_target::spec::abi::Abi; - -use crate::*; -use shims::foreign_items::EmulateForeignItemResult; - -impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {} - -pub fn is_dyn_sym(_name: &str) -> bool { - false -} - -pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { - #[allow(unused, clippy::match_single_binding)] // FIXME: there isn't anything here yet - fn emulate_foreign_item_inner( - &mut self, - link_name: Symbol, - abi: Abi, - args: &[OpTy<'tcx, Provenance>], - dest: &PlaceTy<'tcx, Provenance>, - ) -> InterpResult<'tcx, EmulateForeignItemResult> { - let this = self.eval_context_mut(); - - match link_name.as_str() { - _ => return Ok(EmulateForeignItemResult::NotSupported), - } - - Ok(EmulateForeignItemResult::NeedsJumping) - } -} diff --git a/src/tools/miri/src/shims/unix/android/mod.rs b/src/tools/miri/src/shims/unix/android/mod.rs deleted file mode 100644 index 09c6507b24f..00000000000 --- a/src/tools/miri/src/shims/unix/android/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod foreign_items; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index 7bc26788b26..c1c3e3fa10c 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -15,7 +15,6 @@ use shims::unix::mem::EvalContextExt as _; use shims::unix::sync::EvalContextExt as _; use shims::unix::thread::EvalContextExt as _; -use shims::unix::android::foreign_items as android; use shims::unix::freebsd::foreign_items as freebsd; use shims::unix::linux::foreign_items as linux; use shims::unix::macos::foreign_items as macos; @@ -32,11 +31,10 @@ fn is_dyn_sym(name: &str, target_os: &str) -> bool { // Give specific OSes a chance to allow their symbols. _ => match target_os { - "android" => android::is_dyn_sym(name), "freebsd" => freebsd::is_dyn_sym(name), "linux" => linux::is_dyn_sym(name), "macos" => macos::is_dyn_sym(name), - target_os => panic!("unsupported Unix OS {target_os}"), + _ => false, }, } } @@ -706,7 +704,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { _ => { let target_os = &*this.tcx.sess.target.os; return match target_os { - "android" => android::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "freebsd" => freebsd::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "linux" => linux::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), "macos" => macos::EvalContextExt::emulate_foreign_item_inner(this, link_name, abi, args, dest), diff --git a/src/tools/miri/src/shims/unix/mod.rs b/src/tools/miri/src/shims/unix/mod.rs index 2f801493352..638473da02b 100644 --- a/src/tools/miri/src/shims/unix/mod.rs +++ b/src/tools/miri/src/shims/unix/mod.rs @@ -5,7 +5,6 @@ mod mem; mod sync; mod thread; -mod android; mod freebsd; mod linux; mod macos; From 28550240634a36ddd0696823dff89c84805e10bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= <eduardosm-dev@e64.io> Date: Thu, 23 Nov 2023 20:14:12 +0100 Subject: [PATCH 12/22] Refactor `float_to_int_checked` to remove its generic parameter and reduce code duplication a bit --- src/tools/miri/src/helpers.rs | 104 ++++++++++-------- src/tools/miri/src/shims/intrinsics/mod.rs | 38 ++----- src/tools/miri/src/shims/intrinsics/simd.rs | 17 +-- src/tools/miri/src/shims/x86/mod.rs | 39 ++++++- src/tools/miri/src/shims/x86/sse.rs | 4 +- src/tools/miri/src/shims/x86/sse2.rs | 90 +++++---------- src/tools/miri/src/shims/x86/sse41.rs | 2 +- .../intrinsics/float_to_int_32_inf1.stderr | 4 +- .../intrinsics/float_to_int_32_infneg1.stderr | 4 +- .../intrinsics/float_to_int_32_nan.stderr | 4 +- .../intrinsics/float_to_int_32_nanneg.stderr | 4 +- .../intrinsics/float_to_int_32_neg.stderr | 4 +- .../float_to_int_32_too_big1.stderr | 4 +- .../float_to_int_32_too_big2.stderr | 4 +- .../float_to_int_32_too_small1.stderr | 4 +- .../intrinsics/float_to_int_64_inf1.stderr | 4 +- .../intrinsics/float_to_int_64_infneg1.stderr | 4 +- .../intrinsics/float_to_int_64_infneg2.stderr | 4 +- .../intrinsics/float_to_int_64_nan.stderr | 4 +- .../intrinsics/float_to_int_64_neg.stderr | 4 +- .../float_to_int_64_too_big1.stderr | 4 +- .../float_to_int_64_too_big2.stderr | 4 +- .../float_to_int_64_too_big3.stderr | 4 +- .../float_to_int_64_too_big4.stderr | 4 +- .../float_to_int_64_too_big5.stderr | 4 +- .../float_to_int_64_too_big6.stderr | 4 +- .../float_to_int_64_too_big7.stderr | 4 +- .../float_to_int_64_too_small1.stderr | 4 +- .../float_to_int_64_too_small2.stderr | 4 +- .../float_to_int_64_too_small3.stderr | 4 +- .../fail/intrinsics/simd-float-to-int.stderr | 4 +- 31 files changed, 185 insertions(+), 205 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 650008b98ed..21f1d684924 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -5,17 +5,18 @@ use std::time::Duration; use log::trace; +use rustc_apfloat::ieee::{Double, Single}; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::ty::{ self, - layout::{IntegerExt as _, LayoutOf, TyAndLayout}, - IntTy, Ty, TyCtxt, UintTy, + layout::{LayoutOf, TyAndLayout}, + FloatTy, IntTy, Ty, TyCtxt, UintTy, }; use rustc_span::{def_id::CrateNum, sym, Span, Symbol}; -use rustc_target::abi::{Align, FieldIdx, FieldsShape, Integer, Size, Variants}; +use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants}; use rustc_target::spec::abi::Abi; use rand::RngCore; @@ -986,65 +987,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - /// Converts `f` to integer type `dest_ty` after rounding with mode `round`. + /// Converts `src` from floating point to integer type `dest_ty` + /// after rounding with mode `round`. /// Returns `None` if `f` is NaN or out of range. - fn float_to_int_checked<F>( + fn float_to_int_checked( &self, - f: F, + src: &ImmTy<'tcx, Provenance>, cast_to: TyAndLayout<'tcx>, round: rustc_apfloat::Round, - ) -> Option<ImmTy<'tcx, Provenance>> - where - F: rustc_apfloat::Float + Into<Scalar<Provenance>>, - { + ) -> InterpResult<'tcx, Option<ImmTy<'tcx, Provenance>>> { let this = self.eval_context_ref(); - let val = match cast_to.ty.kind() { - // Unsigned - ty::Uint(t) => { - let size = Integer::from_uint_ty(this, *t).size(); - let res = f.to_u128_r(size.bits_usize(), round, &mut false); - if res.status.intersects( - rustc_apfloat::Status::INVALID_OP - | rustc_apfloat::Status::OVERFLOW - | rustc_apfloat::Status::UNDERFLOW, - ) { - // Floating point value is NaN (flagged with INVALID_OP) or outside the range - // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). - return None; - } else { - // Floating point value can be represented by the integer type after rounding. - // The INEXACT flag is ignored on purpose to allow rounding. - Scalar::from_uint(res.value, size) + fn float_to_int_inner<'tcx, F: rustc_apfloat::Float>( + this: &MiriInterpCx<'_, 'tcx>, + src: F, + cast_to: TyAndLayout<'tcx>, + round: rustc_apfloat::Round, + ) -> (Scalar<Provenance>, rustc_apfloat::Status) { + let int_size = cast_to.layout.size; + match cast_to.ty.kind() { + // Unsigned + ty::Uint(_) => { + let res = src.to_u128_r(int_size.bits_usize(), round, &mut false); + (Scalar::from_uint(res.value, int_size), res.status) } - } - // Signed - ty::Int(t) => { - let size = Integer::from_int_ty(this, *t).size(); - let res = f.to_i128_r(size.bits_usize(), round, &mut false); - if res.status.intersects( - rustc_apfloat::Status::INVALID_OP - | rustc_apfloat::Status::OVERFLOW - | rustc_apfloat::Status::UNDERFLOW, - ) { - // Floating point value is NaN (flagged with INVALID_OP) or outside the range - // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). - return None; - } else { - // Floating point value can be represented by the integer type after rounding. - // The INEXACT flag is ignored on purpose to allow rounding. - Scalar::from_int(res.value, size) + // Signed + ty::Int(_) => { + let res = src.to_i128_r(int_size.bits_usize(), round, &mut false); + (Scalar::from_int(res.value, int_size), res.status) } + // Nothing else + _ => + span_bug!( + this.cur_span(), + "attempted float-to-int conversion with non-int output type {}", + cast_to.ty, + ), } + } + + let (val, status) = match src.layout.ty.kind() { + // f32 + ty::Float(FloatTy::F32) => + float_to_int_inner::<Single>(this, src.to_scalar().to_f32()?, cast_to, round), + // f64 + ty::Float(FloatTy::F64) => + float_to_int_inner::<Double>(this, src.to_scalar().to_f64()?, cast_to, round), // Nothing else _ => span_bug!( this.cur_span(), - "attempted float-to-int conversion with non-int output type {}", - cast_to.ty, + "attempted float-to-int conversion with non-float input type {}", + src.layout.ty, ), }; - Some(ImmTy::from_scalar(val, cast_to)) + + if status.intersects( + rustc_apfloat::Status::INVALID_OP + | rustc_apfloat::Status::OVERFLOW + | rustc_apfloat::Status::UNDERFLOW, + ) { + // Floating point value is NaN (flagged with INVALID_OP) or outside the range + // of values of the integer type (flagged with OVERFLOW or UNDERFLOW). + Ok(None) + } else { + // Floating point value can be represented by the integer type after rounding. + // The INEXACT flag is ignored on purpose to allow rounding. + Ok(Some(ImmTy::from_scalar(val, cast_to))) + } } /// Returns an integer type that is twice wide as `ty` diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index 8c90ceba1e4..66918db995d 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -365,36 +365,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let [val] = check_arg_count(args)?; let val = this.read_immediate(val)?; - let res = match val.layout.ty.kind() { - ty::Float(FloatTy::F32) => { - let f = val.to_scalar().to_f32()?; - this - .float_to_int_checked(f, dest.layout, Round::TowardZero) - .ok_or_else(|| { - err_ub_format!( - "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`", - dest.layout.ty - ) - })? - } - ty::Float(FloatTy::F64) => { - let f = val.to_scalar().to_f64()?; - this - .float_to_int_checked(f, dest.layout, Round::TowardZero) - .ok_or_else(|| { - err_ub_format!( - "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`", - dest.layout.ty - ) - })? - } - _ => - span_bug!( - this.cur_span(), - "`float_to_int_unchecked` called with non-float input type {:?}", - val.layout.ty - ), - }; + let res = this + .float_to_int_checked(&val, dest.layout, Round::TowardZero)? + .ok_or_else(|| { + err_ub_format!( + "`float_to_int_unchecked` intrinsic called on {val} which cannot be represented in target type `{:?}`", + dest.layout.ty + ) + })?; this.write_immediate(*res, dest)?; } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index 70f90aac2c2..d0a293d5f81 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -447,22 +447,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast => this.float_to_float_or_int(&op, dest.layout)?, // Float-to-int in unchecked mode - (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { - let f = op.to_scalar().to_f32()?; - this.float_to_int_checked(f, dest.layout, Round::TowardZero) + (ty::Float(_), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { + this.float_to_int_checked(&op, dest.layout, Round::TowardZero)? .ok_or_else(|| { err_ub_format!( - "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", - dest.layout.ty - ) - })? - } - (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => { - let f = op.to_scalar().to_f64()?; - this.float_to_int_checked(f, dest.layout, Round::TowardZero) - .ok_or_else(|| { - err_ub_format!( - "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", + "`simd_cast` intrinsic called on {op} which cannot be represented in target type `{:?}`", dest.layout.ty ) })? diff --git a/src/tools/miri/src/shims/x86/mod.rs b/src/tools/miri/src/shims/x86/mod.rs index 78590b08933..2ae269db412 100644 --- a/src/tools/miri/src/shims/x86/mod.rs +++ b/src/tools/miri/src/shims/x86/mod.rs @@ -1,4 +1,4 @@ -use rustc_middle::mir; +use rustc_middle::{mir, ty}; use rustc_span::Symbol; use rustc_target::abi::Size; use rustc_target::spec::abi::Abi; @@ -331,6 +331,43 @@ fn bin_op_simd_float_all<'tcx, F: rustc_apfloat::Float>( Ok(()) } +/// Converts each element of `op` from floating point to signed integer. +/// +/// When the input value is NaN or out of range, fall back to minimum value. +/// +/// If `op` has more elements than `dest`, extra elements are ignored. If `op` +/// has less elements than `dest`, the rest is filled with zeros. +fn convert_float_to_int<'tcx>( + this: &mut crate::MiriInterpCx<'_, 'tcx>, + op: &OpTy<'tcx, Provenance>, + rnd: rustc_apfloat::Round, + dest: &PlaceTy<'tcx, Provenance>, +) -> InterpResult<'tcx, ()> { + let (op, op_len) = this.operand_to_simd(op)?; + let (dest, dest_len) = this.place_to_simd(dest)?; + + // Output must be *signed* integers. + assert!(matches!(dest.layout.field(this, 0).ty.kind(), ty::Int(_))); + + for i in 0..op_len.min(dest_len) { + let op = this.read_immediate(&this.project_index(&op, i)?)?; + let dest = this.project_index(&dest, i)?; + + let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| { + // Fallback to minimum acording to SSE/AVX semantics. + ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) + }); + this.write_immediate(*res, &dest)?; + } + // Fill remainder with zeros + for i in op_len..dest_len { + let dest = this.project_index(&dest, i)?; + this.write_scalar(Scalar::from_int(0, dest.layout.size), &dest)?; + } + + Ok(()) +} + /// Horizontaly performs `which` operation on adjacent values of /// `left` and `right` SIMD vectors and stores the result in `dest`. fn horizontal_bin_op<'tcx>( diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs index 8cdb3402f0c..6e06f62b34c 100644 --- a/src/tools/miri/src/shims/x86/sse.rs +++ b/src/tools/miri/src/shims/x86/sse.rs @@ -168,7 +168,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, _) = this.operand_to_simd(op)?; - let op = this.read_scalar(&this.project_index(&op, 0)?)?.to_f32()?; + let op = this.read_immediate(&this.project_index(&op, 0)?)?; let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest @@ -180,7 +180,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: _ => unreachable!(), }; - let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { + let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| { // Fallback to minimum acording to SSE semantics. ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) }); diff --git a/src/tools/miri/src/shims/x86/sse2.rs b/src/tools/miri/src/shims/x86/sse2.rs index 01496b319f1..49bf7547ab0 100644 --- a/src/tools/miri/src/shims/x86/sse2.rs +++ b/src/tools/miri/src/shims/x86/sse2.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::spec::abi::Abi; -use super::{bin_op_simd_float_all, bin_op_simd_float_first, FloatBinOp}; +use super::{bin_op_simd_float_all, bin_op_simd_float_first, convert_float_to_int, FloatBinOp}; use crate::*; use shims::foreign_items::EmulateForeignItemResult; @@ -260,37 +260,42 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: this.write_scalar(Scalar::from_u64(res), &dest)?; } } - // Used to implement the _mm_cvtps_epi32 and _mm_cvttps_epi32 functions. - // Converts packed f32 to packed i32. - "cvtps2dq" | "cvttps2dq" => { + // Used to implement the _mm_cvtps_epi32, _mm_cvttps_epi32, _mm_cvtpd_epi32 + // and _mm_cvttpd_epi32 functions. + // Converts packed f32/f64 to packed i32. + "cvtps2dq" | "cvttps2dq" | "cvtpd2dq" | "cvttpd2dq" => { let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; - - assert_eq!(dest_len, op_len); + let (op_len, _) = op.layout.ty.simd_size_and_type(*this.tcx); + let (dest_len, _) = dest.layout.ty.simd_size_and_type(*this.tcx); + match unprefixed_name { + "cvtps2dq" | "cvttps2dq" => { + // f32x4 to i32x4 conversion + assert_eq!(op_len, 4); + assert_eq!(dest_len, op_len); + } + "cvtpd2dq" | "cvttpd2dq" => { + // f64x2 to i32x4 conversion + // the last two values are filled with zeros + assert_eq!(op_len, 2); + assert_eq!(dest_len, 4); + } + _ => unreachable!(), + } let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest // https://www.felixcloutier.com/x86/cvtps2dq - "cvtps2dq" => rustc_apfloat::Round::NearestTiesToEven, + // https://www.felixcloutier.com/x86/cvtpd2dq + "cvtps2dq" | "cvtpd2dq" => rustc_apfloat::Round::NearestTiesToEven, // always truncate // https://www.felixcloutier.com/x86/cvttps2dq - "cvttps2dq" => rustc_apfloat::Round::TowardZero, + // https://www.felixcloutier.com/x86/cvttpd2dq + "cvttps2dq" | "cvttpd2dq" => rustc_apfloat::Round::TowardZero, _ => unreachable!(), }; - for i in 0..dest_len { - let op = this.read_scalar(&this.project_index(&op, i)?)?.to_f32()?; - let dest = this.project_index(&dest, i)?; - - let res = - this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { - // Fallback to minimum acording to SSE2 semantics. - ImmTy::from_int(i32::MIN, this.machine.layouts.i32) - }); - this.write_immediate(*res, &dest)?; - } + convert_float_to_int(this, op, rnd, dest)?; } // Used to implement the _mm_packs_epi16 function. // Converts two 16-bit integer vectors to a single 8-bit integer @@ -527,45 +532,6 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: }; this.write_scalar(Scalar::from_i32(i32::from(res)), dest)?; } - // Used to implement the _mm_cvtpd_epi32 and _mm_cvttpd_epi32 functions. - // Converts packed f64 to packed i32. - "cvtpd2dq" | "cvttpd2dq" => { - let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; - - let (op, op_len) = this.operand_to_simd(op)?; - let (dest, dest_len) = this.place_to_simd(dest)?; - - // op is f64x2, dest is i32x4 - assert_eq!(op_len, 2); - assert_eq!(dest_len, 4); - - let rnd = match unprefixed_name { - // "current SSE rounding mode", assume nearest - // https://www.felixcloutier.com/x86/cvtpd2dq - "cvtpd2dq" => rustc_apfloat::Round::NearestTiesToEven, - // always truncate - // https://www.felixcloutier.com/x86/cvttpd2dq - "cvttpd2dq" => rustc_apfloat::Round::TowardZero, - _ => unreachable!(), - }; - - for i in 0..op_len { - let op = this.read_scalar(&this.project_index(&op, i)?)?.to_f64()?; - let dest = this.project_index(&dest, i)?; - - let res = - this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { - // Fallback to minimum acording to SSE2 semantics. - ImmTy::from_int(i32::MIN, this.machine.layouts.i32) - }); - this.write_immediate(*res, &dest)?; - } - // Fill the remaining with zeros - for i in op_len..dest_len { - let dest = this.project_index(&dest, i)?; - this.write_scalar(Scalar::from_i32(0), &dest)?; - } - } // Use to implement the _mm_cvtsd_si32, _mm_cvttsd_si32, // _mm_cvtsd_si64 and _mm_cvttsd_si64 functions. // Converts the first component of `op` from f64 to i32/i64. @@ -573,7 +539,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: let [op] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let (op, _) = this.operand_to_simd(op)?; - let op = this.read_scalar(&this.project_index(&op, 0)?)?.to_f64()?; + let op = this.read_immediate(&this.project_index(&op, 0)?)?; let rnd = match unprefixed_name { // "current SSE rounding mode", assume nearest @@ -585,7 +551,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: _ => unreachable!(), }; - let res = this.float_to_int_checked(op, dest.layout, rnd).unwrap_or_else(|| { + let res = this.float_to_int_checked(&op, dest.layout, rnd)?.unwrap_or_else(|| { // Fallback to minimum acording to SSE semantics. ImmTy::from_int(dest.layout.size.signed_int_min(), dest.layout) }); diff --git a/src/tools/miri/src/shims/x86/sse41.rs b/src/tools/miri/src/shims/x86/sse41.rs index d9bccecb497..b3d1056ab06 100644 --- a/src/tools/miri/src/shims/x86/sse41.rs +++ b/src/tools/miri/src/shims/x86/sse41.rs @@ -200,7 +200,7 @@ pub(super) trait EvalContextExt<'mir, 'tcx: 'mir>: Scalar::from_u16(min_index.try_into().unwrap()), &this.project_index(&dest, 1)?, )?; - // Fill remaining with zeros + // Fill remainder with zeros for i in 2..dest_len { this.write_scalar(Scalar::from_u16(0), &this.project_index(&dest, i)?)?; } diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr index c82d6b30224..27318c0a98d 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_inf1.rs:LL:CC | LL | float_to_int_unchecked::<f32, i32>(f32::INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr index 4ca41b676e9..bcf6b9015c1 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_infneg1.rs:LL:CC | LL | float_to_int_unchecked::<f32, i32>(f32::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff32 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr index 88b8948b0c2..3e71fd10058 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_nan.rs:LL:CC | LL | float_to_int_unchecked::<f32, u32>(f32::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr index ca798dd391a..479ea2c6b6f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_nanneg.rs:LL:CC | LL | float_to_int_unchecked::<f32, u32>(-f32::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr index 4ff6eb80985..ae17d676174 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_neg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_neg.rs:LL:CC | LL | float_to_int_unchecked::<f32, u32>(-1.000000001f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1f32 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr index fd17709d164..9edda4f2027 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.14748365E+9 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.14748365E+9f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_too_big1.rs:LL:CC | LL | float_to_int_unchecked::<f32, i32>(2147483648.0f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.14748365E+9 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.14748365E+9f32 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr index fdc1f65dc14..7b394f97fd1 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_big2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 4.2949673E+9 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 4.2949673E+9f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_too_big2.rs:LL:CC | LL | float_to_int_unchecked::<f32, u32>((u32::MAX - 127) as f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 4.2949673E+9 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 4.2949673E+9f32 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr index 9e743a32144..1d8ab4b3cb1 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_too_small1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.1474839E+9 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.1474839E+9f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_too_small1.rs:LL:CC | LL | float_to_int_unchecked::<f32, i32>(-2147483904.0f32); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.1474839E+9 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.1474839E+9f32 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr index ee01143dc8d..857bd355fc5 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_inf1.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(f64::INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inff64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr index f37b8ae5506..fc089182e6b 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_infneg1.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr index 05dcd5ebcf6..c5d99c4d360 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_infneg2.rs:LL:CC | LL | float_to_int_unchecked::<f64, i128>(f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `i128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr index 0a914abb2ce..05a7da06321 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf64 which cannot be represented in target type `u32` --> $DIR/float_to_int_64_nan.rs:LL:CC | LL | float_to_int_unchecked::<f64, u32>(f64::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf64 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr index ddf3249d059..d1ac6765336 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_neg.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(-1.0000000000001f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999f64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr index 42da33321f3..3122c83f970 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2147483648 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2147483648f64 which cannot be represented in target type `i32` --> $DIR/float_to_int_64_too_big1.rs:LL:CC | LL | float_to_int_unchecked::<f64, i32>(2147483648.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2147483648 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2147483648f64 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr index af4c4ceb3f7..8db497e2c00 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18 which cannot be represented in target type `i64` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18f64 which cannot be represented in target type `i64` --> $DIR/float_to_int_64_too_big2.rs:LL:CC | LL | float_to_int_unchecked::<f64, i64>(9223372036854775808.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18 which cannot be represented in target type `i64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 9.2233720368547758E+18f64 which cannot be represented in target type `i64` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr index 6e384a6fbc7..2a2de75f4bd 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big3.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19 which cannot be represented in target type `u64` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19f64 which cannot be represented in target type `u64` --> $DIR/float_to_int_64_too_big3.rs:LL:CC | LL | float_to_int_unchecked::<f64, u64>(18446744073709551616.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19 which cannot be represented in target type `u64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.8446744073709552E+19f64 which cannot be represented in target type `u64` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr index 77f05ff91e3..0e29fc7cd07 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big4.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_too_big4.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(u128::MAX as f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.4028236692093846E+38f64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr index cb5eba490b4..d5d79d455f9 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big5.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_too_big5.rs:LL:CC | LL | float_to_int_unchecked::<f64, i128>(240282366920938463463374607431768211455.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 2.4028236692093845E+38f64 which cannot be represented in target type `i128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr index d899d2f808a..d7e87b62af0 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big6.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_too_big6.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(f64::MAX); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 1.7976931348623157E+308f64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr index 443b2759c26..4e3751da9a3 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_big7.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_too_big7.rs:LL:CC | LL | float_to_int_unchecked::<f64, i128>(f64::MIN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.7976931348623157E+308f64 which cannot be represented in target type `i128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr index f8d88c44aa8..610702371d7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2147483649 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2147483649f64 which cannot be represented in target type `i32` --> $DIR/float_to_int_64_too_small1.rs:LL:CC | LL | float_to_int_unchecked::<f64, i32>(-2147483649.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2147483649 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2147483649f64 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr index d94e57b1e67..e92655af2a8 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18 which cannot be represented in target type `i64` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18f64 which cannot be represented in target type `i64` --> $DIR/float_to_int_64_too_small2.rs:LL:CC | LL | float_to_int_unchecked::<f64, i64>(-9223372036854777856.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18 which cannot be represented in target type `i64` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -9.2233720368547778E+18f64 which cannot be represented in target type `i64` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr index 59b74f5f51f..7d81945476f 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_too_small3.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_too_small3.rs:LL:CC | LL | float_to_int_unchecked::<f64, i128>(-240282366920938463463374607431768211455.0f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -2.4028236692093845E+38f64 which cannot be represented in target type `i128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr index 7b2387944af..df4792f8d80 100644 --- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr +++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32` +error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32` --> $DIR/simd-float-to-int.rs:LL:CC | LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38f32 which cannot be represented in target type `i32` | = 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 From c17444876bcc827e0e4223b193ea40a0f4253b21 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 08:00:32 +0100 Subject: [PATCH 13/22] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ee27d8ed9a8..76ae9227983 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -360bafad68cfea2682cf016070e533c45a00150f +34c5ab9aac327a8a18e18ea37a2468a320d82fb0 From 2df4fc0e8b6210b9f2807b26717000f3c69034a4 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 08:03:51 +0100 Subject: [PATCH 14/22] fmt --- src/tools/miri/src/provenance_gc.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/tools/miri/src/provenance_gc.rs b/src/tools/miri/src/provenance_gc.rs index b5106c22740..ab178f82d9f 100644 --- a/src/tools/miri/src/provenance_gc.rs +++ b/src/tools/miri/src/provenance_gc.rs @@ -194,10 +194,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: MiriInterpCxExt<'mir, 'tcx> { fn remove_unreachable_allocs(&mut self, allocs: FxHashSet<AllocId>) { let this = self.eval_context_mut(); - let allocs = LiveAllocs { - ecx: this, - collected: allocs, - }; + let allocs = LiveAllocs { ecx: this, collected: allocs }; this.machine.allocation_spans.borrow_mut().retain(|id, _| allocs.is_live(*id)); this.machine.intptrcast.borrow_mut().remove_unreachable_allocs(&allocs); if let Some(borrow_tracker) = &this.machine.borrow_tracker { From 34a8680cd50a20e5a2f5a7a6861d7c8b700dc3c6 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 08:27:42 +0100 Subject: [PATCH 15/22] bless --- .../miri/tests/fail-dep/shims/env-set_var-data-race.stderr | 2 +- src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr index a202d7c6844..b81e8db9e0c 100644 --- a/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr +++ b/src/tools/miri/tests/fail-dep/shims/env-set_var-data-race.stderr @@ -16,5 +16,5 @@ LL | env::set_var("MY_RUST_VAR", "Ferris"); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error diff --git a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr index c034261338a..8e83d20854f 100644 --- a/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr +++ b/src/tools/miri/tests/fail/shims/intrinsic_target_feature.stderr @@ -11,5 +11,5 @@ LL | dpps(_mm_setzero_ps(), _mm_setzero_ps(), 0); note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace -error: aborting due to previous error +error: aborting due to 1 previous error From 69ea9520d3b7dee9df59128acec43f9b15aa3ee2 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 10:15:17 +0100 Subject: [PATCH 16/22] make tests/utils work with edition 2015 --- src/tools/miri/tests/utils/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/tests/utils/mod.rs b/src/tools/miri/tests/utils/mod.rs index 3b817667f13..cb9380f5753 100644 --- a/src/tools/miri/tests/utils/mod.rs +++ b/src/tools/miri/tests/utils/mod.rs @@ -7,8 +7,8 @@ mod macros; mod fs; mod miri_extern; -pub use fs::*; -pub use miri_extern::*; +pub use self::fs::*; +pub use self::miri_extern::*; pub fn run_provenance_gc() { // SAFETY: No preconditions. The GC is fine to run at any time. From ce94b22cd6130a560155f02b8634f117f7fd36c6 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 10:29:22 +0100 Subject: [PATCH 17/22] read off_t at the right size for the current target --- src/tools/miri/src/shims/unix/foreign_items.rs | 4 ++-- src/tools/miri/src/shims/unix/fs.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index c1c3e3fa10c..23342c8045e 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -163,14 +163,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let fd = this.read_scalar(fd)?.to_i32()?; let length = this.read_scalar(length)?.to_i64()?; - let result = this.ftruncate64(fd, length)?; + let result = this.ftruncate64(fd, length.into())?; this.write_scalar(result, dest)?; } "ftruncate" => { let [fd, length] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?; let fd = this.read_scalar(fd)?.to_i32()?; - let length = this.read_target_isize(length)?; + let length = this.read_scalar(length)?.to_int(this.libc_ty_layout("off_t").size)?; let result = this.ftruncate64(fd, length)?; this.write_scalar(result, dest)?; } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index d545cb46069..ba40a1b3c32 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1504,7 +1504,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { } } - fn ftruncate64(&mut self, fd: i32, length: i64) -> InterpResult<'tcx, Scalar<Provenance>> { + fn ftruncate64(&mut self, fd: i32, length: i128) -> InterpResult<'tcx, Scalar<Provenance>> { let this = self.eval_context_mut(); // Reject if isolation is enabled. From b750b5495821063f0746ad0c516f65b17cc6ff51 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 10:29:31 +0100 Subject: [PATCH 18/22] run tests on 32bit freebsd --- src/tools/miri/ci.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 378d7744cf2..b8f90b8df6c 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -109,6 +109,7 @@ case $HOST_TARGET in MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align + MIRI_TEST_TARGET=i686-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm MIRI_TEST_TARGET=wasm32-unknown-unknown run_tests_minimal no_std integer strings wasm From 2a89b74bc75d1b30f5e71091cc66fc9f5789d69a Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 10:11:05 +0100 Subject: [PATCH 19/22] run the provenance-gc=1 test on all targets, but only for some of the tests before: only on Linux host, all tests after: only the test suite itself (not cargo-miri or the mir-opt-level=4 run), on all hosts for the host target and on Linux for all "full" targets. --- src/tools/miri/.github/workflows/ci.yml | 4 ---- src/tools/miri/ci.sh | 17 ++++++++++++----- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 554a12909fc..dec85e9232f 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -35,10 +35,6 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set the tag GC interval to 1 on linux - if: runner.os == 'Linux' - run: echo "MIRIFLAGS=-Zmiri-provenance-gc=1" >> $GITHUB_ENV - # Cache the global cargo directory, but NOT the local `target` directory which # we cannot reuse anyway when the nightly changes (and it grows quite large # over time). diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 378d7744cf2..0492953671e 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -30,16 +30,23 @@ endgroup # Test function run_tests { - if [ -n "${MIRI_TEST_TARGET+exists}" ]; then + if [ -n "${MIRI_TEST_TARGET:-}" ]; then begingroup "Testing foreign architecture $MIRI_TEST_TARGET" else begingroup "Testing host architecture" fi ## ui test suite - ./miri test - if [ -z "${MIRI_TEST_TARGET+exists}" ]; then - # Host-only tests: running these on all targets is unlikely to catch more problems and would + # On the host and on Linux, also stress-test the GC. + if [ -z "${MIRI_TEST_TARGET:-}" ] || [ "$HOST_TARGET" = x86_64-unknown-linux-gnu ]; then + MIRIFLAGS="${MIRIFLAGS:-} -Zmiri-provenance-gc=1" ./miri test + else + ./miri test + fi + + # Host-only tests + if [ -z "${MIRI_TEST_TARGET:-}" ]; then + # Running these on all targets is unlikely to catch more problems and would # cost a lot of CI time. # Tests with optimizations (`-O` is what cargo passes, but crank MIR optimizations up all the @@ -85,7 +92,7 @@ function run_tests { } function run_tests_minimal { - if [ -n "${MIRI_TEST_TARGET+exists}" ]; then + if [ -n "${MIRI_TEST_TARGET:-}" ]; then begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@" else begingroup "Testing MINIMAL host architecture: only testing $@" From 695f1a515e532e079545982b63906233879959f4 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 13:09:35 +0100 Subject: [PATCH 20/22] tweak ci.sh --- src/tools/miri/ci.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh index 0492953671e..34892489c80 100755 --- a/src/tools/miri/ci.sh +++ b/src/tools/miri/ci.sh @@ -95,7 +95,8 @@ function run_tests_minimal { if [ -n "${MIRI_TEST_TARGET:-}" ]; then begingroup "Testing MINIMAL foreign architecture $MIRI_TEST_TARGET: only testing $@" else - begingroup "Testing MINIMAL host architecture: only testing $@" + echo "run_tests_minimal requires MIRI_TEST_TARGET to be set" + exit 1 fi ./miri test -- "$@" @@ -106,15 +107,20 @@ function run_tests_minimal { endgroup } -# host +## Main Testing Logic ## + +# Host target. run_tests +# Extra targets. +# In particular, fully cover all tier 1 targets. case $HOST_TARGET in x86_64-unknown-linux-gnu) MIRI_TEST_TARGET=i686-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-unknown-linux-gnu run_tests MIRI_TEST_TARGET=aarch64-apple-darwin run_tests MIRI_TEST_TARGET=i686-pc-windows-gnu run_tests + # Some targets are only partially supported. MIRI_TEST_TARGET=x86_64-unknown-freebsd run_tests_minimal hello integer vec panic/panic concurrency/simple pthread-threadname libc-getentropy libc-getrandom libc-misc libc-fs atomic env align MIRI_TEST_TARGET=aarch64-linux-android run_tests_minimal hello integer vec panic/panic MIRI_TEST_TARGET=wasm32-wasi run_tests_minimal no_std integer strings wasm From 2f825fb3d45c622fa7bc0d453fd13773c4f8a199 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 14:19:37 +0100 Subject: [PATCH 21/22] Preparing for merge from rustc --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 76ae9227983..ecebb8a331b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -34c5ab9aac327a8a18e18ea37a2468a320d82fb0 +3668a8af1b81447c4afa1f82f60d7b94b71a549f From feb37829e152e0880dffa337e4897f75ca35eb84 Mon Sep 17 00:00:00 2001 From: Ralf Jung <post@ralfj.de> Date: Sat, 25 Nov 2023 14:26:00 +0100 Subject: [PATCH 22/22] bless --- .../miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_32_nan.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr | 4 ++-- .../miri/tests/fail/intrinsics/float_to_int_64_nan.stderr | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr index 9ed527d850d..2de8f3420b7 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_inf1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_inf1.rs:LL:CC | LL | float_to_int_unchecked::<f32, i32>(f32::INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inff32 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f32 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr index d1aaaf26a30..53ed208bdee 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_infneg1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff32 which cannot be represented in target type `i32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32` --> $DIR/float_to_int_32_infneg1.rs:LL:CC | LL | float_to_int_unchecked::<f32, i32>(f32::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff32 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f32 which cannot be represented in target type `i32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr index bd00f00e70a..afda7124c11 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nan.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_nan.rs:LL:CC | LL | float_to_int_unchecked::<f32, u32>(f32::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr index ab717efbfe0..8ba46de8641 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_32_nanneg.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` --> $DIR/float_to_int_32_nanneg.rs:LL:CC | LL | float_to_int_unchecked::<f32, u32>(-f32::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf32 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f32 which cannot be represented in target type `u32` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr index c68fd64f62a..5db9fb1417c 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_inf1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inff64 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_inf1.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(f64::INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inff64 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on +Inf_f64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr index 83b6c04bb1d..3e8dadb79e4 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg1.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `u128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128` --> $DIR/float_to_int_64_infneg1.rs:LL:CC | LL | float_to_int_unchecked::<f64, u128>(f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `u128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `u128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr index b7bfe1f7dd9..cb59974bf45 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_infneg2.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `i128` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128` --> $DIR/float_to_int_64_infneg2.rs:LL:CC | LL | float_to_int_unchecked::<f64, i128>(f64::NEG_INFINITY); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inff64 which cannot be represented in target type `i128` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -Inf_f64 which cannot be represented in target type `i128` | = 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 diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr index 1df594bce43..68697060515 100644 --- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr +++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_nan.stderr @@ -1,8 +1,8 @@ -error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaNf64 which cannot be represented in target type `u32` +error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32` --> $DIR/float_to_int_64_nan.rs:LL:CC | LL | float_to_int_unchecked::<f64, u32>(f64::NAN); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaNf64 which cannot be represented in target type `u32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on NaN_f64 which cannot be represented in target type `u32` | = 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