Remove float_to_int_unchecked and inline it into its call sites

This commit is contained in:
Eduardo Sánchez Muñoz 2023-08-11 20:23:08 +02:00
parent fe35dd1afc
commit 29b38ed76a
3 changed files with 56 additions and 39 deletions

View File

@ -9,7 +9,7 @@ use rustc_apfloat::{Float, Round};
use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::{ use rustc_middle::{
mir, mir,
ty::{self, FloatTy, Ty}, ty::{self, FloatTy},
}; };
use rustc_target::abi::Size; use rustc_target::abi::Size;
@ -356,10 +356,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let val = this.read_immediate(val)?; let val = this.read_immediate(val)?;
let res = match val.layout.ty.kind() { let res = match val.layout.ty.kind() {
ty::Float(FloatTy::F32) => ty::Float(FloatTy::F32) => {
this.float_to_int_unchecked(val.to_scalar().to_f32()?, dest.layout.ty)?, let f = val.to_scalar().to_f32()?;
ty::Float(FloatTy::F64) => this
this.float_to_int_unchecked(val.to_scalar().to_f64()?, dest.layout.ty)?, .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!( span_bug!(
this.cur_span(), this.cur_span(),
@ -383,20 +401,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
Ok(()) Ok(())
} }
fn float_to_int_unchecked<F>(
&self,
f: F,
dest_ty: Ty<'tcx>,
) -> InterpResult<'tcx, Scalar<Provenance>>
where
F: Float + Into<Scalar<Provenance>>,
{
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:?}`",
))?)
}
} }

View File

@ -1,4 +1,4 @@
use rustc_apfloat::Float; use rustc_apfloat::{Float, Round};
use rustc_middle::ty::layout::{HasParamEnv, LayoutOf}; use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
use rustc_middle::{mir, ty, ty::FloatTy}; use rustc_middle::{mir, ty, ty::FloatTy};
use rustc_target::abi::{Endian, HasDataLayout, Size}; use rustc_target::abi::{Endian, HasDataLayout, Size};
@ -420,7 +420,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
} }
} }
} }
#[rustfmt::skip]
"cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => { "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
let [op] = check_arg_count(args)?; let [op] = check_arg_count(args)?;
let (op, op_len) = this.operand_to_simd(op)?; let (op, op_len) = this.operand_to_simd(op)?;
@ -440,7 +439,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) { let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
// Int-to-(int|float): always safe // 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)?, this.int_to_int_or_float(&op, dest.layout.ty)?,
// Float-to-float: always safe // Float-to-float: always safe
(ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast => (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
@ -449,21 +449,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
(ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast => (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
this.float_to_float_or_int(&op, dest.layout.ty)?, this.float_to_float_or_int(&op, dest.layout.ty)?,
// Float-to-int in unchecked mode // Float-to-int in unchecked mode
(ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => (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(), let f = op.to_scalar().to_f32()?;
(ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(), .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 // Ptr-to-ptr cast
(ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => { (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast =>
this.ptr_to_ptr(&op, dest.layout.ty)? this.ptr_to_ptr(&op, dest.layout.ty)?,
}
// Ptr/Int casts // Ptr/Int casts
(ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => { (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast =>
this.pointer_expose_address_cast(&op, dest.layout.ty)? this.pointer_expose_address_cast(&op, dest.layout.ty)?,
} (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast =>
(ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => { this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?,
this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
}
// Error otherwise // Error otherwise
_ => _ =>
throw_unsup_format!( throw_unsup_format!(

View File

@ -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 --> $DIR/simd-float-to-int.rs:LL:CC
| |
LL | let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked(); 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: 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 = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information