Skip to content

Commit

Permalink
Remove float_to_int_unchecked and inline it into its call sites
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardosm committed Aug 11, 2023
1 parent b57bc6d commit 5141436
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 39 deletions.
44 changes: 23 additions & 21 deletions src/shims/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rustc_apfloat::{Float, Round};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::{
mir,
ty::{self, FloatTy, Ty},
ty::{self, FloatTy},
};
use rustc_target::abi::Size;

Expand Down Expand Up @@ -356,10 +356,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
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(),
Expand All @@ -383,20 +401,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {

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:?}`",
))?)
}
}
47 changes: 31 additions & 16 deletions src/shims/intrinsics/simd.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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" => {
let [op] = check_arg_count(args)?;
let (op, op_len) = this.operand_to_simd(op)?;
Expand All @@ -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()) {
// 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 =>
Expand All @@ -449,21 +449,36 @@ 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.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(),
// Ptr-to-ptr cast
(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::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::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
this.pointer_from_exposed_address_cast(&op, 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.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)?,
// 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)?,
// Error otherwise
_ =>
throw_unsup_format!(
Expand Down
4 changes: 2 additions & 2 deletions tests/fail/intrinsics/simd-float-to-int.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit 5141436

Please sign in to comment.