diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs index f0b2850da0f..b2c297fe542 100644 --- a/src/tools/miri/src/shims/intrinsics/mod.rs +++ b/src/tools/miri/src/shims/intrinsics/mod.rs @@ -9,7 +9,7 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_middle::{ mir, - ty::{self, FloatTy, Ty}, + ty::{self, FloatTy}, }; use rustc_target::abi::Size; @@ -356,10 +356,28 @@ fn emulate_intrinsic_by_name( let val = this.read_immediate(val)?; let res = match val.layout.ty.kind() { - ty::Float(FloatTy::F32) => - this.float_to_int_unchecked(val.to_scalar().to_f32()?, dest.layout.ty)?, - ty::Float(FloatTy::F64) => - this.float_to_int_unchecked(val.to_scalar().to_f64()?, dest.layout.ty)?, + ty::Float(FloatTy::F32) => { + let f = val.to_scalar().to_f32()?; + this + .float_to_int_checked(f, dest.layout.ty, 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.ty, 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(), @@ -383,20 +401,4 @@ fn emulate_intrinsic_by_name( Ok(()) } - - fn float_to_int_unchecked( - &self, - f: F, - dest_ty: Ty<'tcx>, - ) -> InterpResult<'tcx, Scalar> - where - F: Float + Into>, - { - let this = self.eval_context_ref(); - Ok(this - .float_to_int_checked(f, dest_ty, Round::TowardZero) - .ok_or_else(|| err_ub_format!( - "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{dest_ty:?}`", - ))?) - } } diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs index b6225713cd0..dd8c4a4f6ec 100644 --- a/src/tools/miri/src/shims/intrinsics/simd.rs +++ b/src/tools/miri/src/shims/intrinsics/simd.rs @@ -1,4 +1,4 @@ -use rustc_apfloat::Float; +use rustc_apfloat::{Float, Round}; use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; use rustc_middle::{mir, ty, ty::FloatTy}; use rustc_target::abi::{Endian, HasDataLayout, Size}; @@ -420,7 +420,6 @@ enum Op { } } } - #[rustfmt::skip] "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => { let [op] = check_arg_count(args)?; let (op, op_len) = this.operand_to_simd(op)?; @@ -440,7 +439,8 @@ enum Op { let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) { // Int-to-(int|float): always safe - (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast => + (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) + if safe_cast || unsafe_cast => this.int_to_int_or_float(&op, dest.layout.ty)?, // Float-to-float: always safe (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast => @@ -449,21 +449,36 @@ enum Op { (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast => this.float_to_float_or_int(&op, dest.layout.ty)?, // Float-to-int in unchecked mode - (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => - this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(), - (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => - this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(), + (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.ty, Round::TowardZero) + .ok_or_else(|| { + err_ub_format!( + "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", + dest.layout.ty + ) + })? + .into() + } + (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.ty, Round::TowardZero) + .ok_or_else(|| { + err_ub_format!( + "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`", + dest.layout.ty + ) + })? + .into() + } // Ptr-to-ptr cast - (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => { - this.ptr_to_ptr(&op, dest.layout.ty)? - } + (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => + this.ptr_to_ptr(&op, dest.layout.ty)?, // Ptr/Int casts - (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => { - this.pointer_expose_address_cast(&op, dest.layout.ty)? - } - (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => { - this.pointer_from_exposed_address_cast(&op, dest.layout.ty)? - } + (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => + this.pointer_expose_address_cast(&op, dest.layout.ty)?, + (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => + this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?, // Error otherwise _ => throw_unsup_format!( 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 ea5ad62aea9..7b2387944af 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: `float_to_int_unchecked` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32` +error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38 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(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38 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