about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-05-12 10:09:45 +0200
committerRalf Jung <post@ralfj.de>2024-05-12 10:12:33 +0200
commit9fc569d67f5e07941ed27d16148df8ebfad0a97b (patch)
treee0eabb43949bd2a22dfe162b9e0187cbbab10096
parentfd5e0374e927f2a3acfa198fb25667f0b5e23044 (diff)
downloadrust-9fc569d67f5e07941ed27d16148df8ebfad0a97b.tar.gz
rust-9fc569d67f5e07941ed27d16148df8ebfad0a97b.zip
organize float intrinsic implementations a bit
-rw-r--r--src/tools/miri/src/intrinsics/mod.rs194
1 files changed, 92 insertions, 102 deletions
diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs
index cf5d9913817..7344846d6d9 100644
--- a/src/tools/miri/src/intrinsics/mod.rs
+++ b/src/tools/miri/src/intrinsics/mod.rs
@@ -167,6 +167,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // This is a "bitwise" operation, so there's no NaN non-determinism.
                 this.write_scalar(Scalar::from_f64(f.abs()), dest)?;
             }
+
             "floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => {
                 let [f] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
@@ -182,6 +183,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
+            "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => {
+                let [f] = check_arg_count(args)?;
+                let f = this.read_scalar(f)?.to_f64()?;
+                let mode = match intrinsic_name {
+                    "floorf64" => Round::TowardNegative,
+                    "ceilf64" => Round::TowardPositive,
+                    "truncf64" => Round::TowardZero,
+                    "roundf64" => Round::NearestTiesToAway,
+                    "rintf64" => Round::NearestTiesToEven,
+                    _ => bug!(),
+                };
+                let res = f.round_to_integral(mode).value;
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
+            }
+
             #[rustfmt::skip]
             | "sinf32"
             | "cosf32"
@@ -211,22 +228,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
-
-            "floorf64" | "ceilf64" | "truncf64" | "roundf64" | "rintf64" => {
-                let [f] = check_arg_count(args)?;
-                let f = this.read_scalar(f)?.to_f64()?;
-                let mode = match intrinsic_name {
-                    "floorf64" => Round::TowardNegative,
-                    "ceilf64" => Round::TowardPositive,
-                    "truncf64" => Round::TowardZero,
-                    "roundf64" => Round::NearestTiesToAway,
-                    "rintf64" => Round::NearestTiesToEven,
-                    _ => bug!(),
-                };
-                let res = f.round_to_integral(mode).value;
-                let res = this.adjust_nan(res, &[f]);
-                this.write_scalar(res, dest)?;
-            }
             #[rustfmt::skip]
             | "sinf64"
             | "cosf64"
@@ -256,84 +257,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
-            #[rustfmt::skip]
-            | "fadd_algebraic"
-            | "fsub_algebraic"
-            | "fmul_algebraic"
-            | "fdiv_algebraic"
-            | "frem_algebraic"
-            => {
-                let [a, b] = check_arg_count(args)?;
-                let a = this.read_immediate(a)?;
-                let b = this.read_immediate(b)?;
-                let op = match intrinsic_name {
-                    "fadd_algebraic" => mir::BinOp::Add,
-                    "fsub_algebraic" => mir::BinOp::Sub,
-                    "fmul_algebraic" => mir::BinOp::Mul,
-                    "fdiv_algebraic" => mir::BinOp::Div,
-                    "frem_algebraic" => mir::BinOp::Rem,
-                    _ => bug!(),
-                };
-                let res = this.wrapping_binary_op(op, &a, &b)?;
-                // `wrapping_binary_op` already called `generate_nan` if necessary.
-                this.write_immediate(*res, dest)?;
-            }
-
-            #[rustfmt::skip]
-            | "fadd_fast"
-            | "fsub_fast"
-            | "fmul_fast"
-            | "fdiv_fast"
-            | "frem_fast"
-            => {
-                let [a, b] = check_arg_count(args)?;
-                let a = this.read_immediate(a)?;
-                let b = this.read_immediate(b)?;
-                let op = match intrinsic_name {
-                    "fadd_fast" => mir::BinOp::Add,
-                    "fsub_fast" => mir::BinOp::Sub,
-                    "fmul_fast" => mir::BinOp::Mul,
-                    "fdiv_fast" => mir::BinOp::Div,
-                    "frem_fast" => mir::BinOp::Rem,
-                    _ => bug!(),
-                };
-                let float_finite = |x: &ImmTy<'tcx, _>| -> InterpResult<'tcx, bool> {
-                    let ty::Float(fty) = x.layout.ty.kind() else {
-                        bug!("float_finite: non-float input type {}", x.layout.ty)
-                    };
-                    Ok(match fty {
-                        FloatTy::F16 => unimplemented!("f16_f128"),
-                        FloatTy::F32 => x.to_scalar().to_f32()?.is_finite(),
-                        FloatTy::F64 => x.to_scalar().to_f64()?.is_finite(),
-                        FloatTy::F128 => unimplemented!("f16_f128"),
-                    })
-                };
-                match (float_finite(&a)?, float_finite(&b)?) {
-                    (false, false) => throw_ub_format!(
-                        "`{intrinsic_name}` intrinsic called with non-finite value as both parameters",
-                    ),
-                    (false, _) => throw_ub_format!(
-                        "`{intrinsic_name}` intrinsic called with non-finite value as first parameter",
-                    ),
-                    (_, false) => throw_ub_format!(
-                        "`{intrinsic_name}` intrinsic called with non-finite value as second parameter",
-                    ),
-                    _ => {}
-                }
-                let res = this.wrapping_binary_op(op, &a, &b)?;
-                if !float_finite(&res)? {
-                    throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result");
-                }
-                // This cannot be a NaN so we also don't have to apply any non-determinism.
-                // (Also, `wrapping_binary_op` already called `generate_nan` if needed.)
-                this.write_immediate(*res, dest)?;
-            }
 
-            #[rustfmt::skip]
-            | "minnumf32"
-            | "maxnumf32"
-            | "copysignf32"
-            => {
+            "minnumf32" | "maxnumf32" | "copysignf32" => {
                 let [a, b] = check_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f32()?;
                 let b = this.read_scalar(b)?.to_f32()?;
@@ -345,12 +270,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 };
                 this.write_scalar(Scalar::from_f32(res), dest)?;
             }
-
-            #[rustfmt::skip]
-            | "minnumf64"
-            | "maxnumf64"
-            | "copysignf64"
-            => {
+            "minnumf64" | "maxnumf64" | "copysignf64" => {
                 let [a, b] = check_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f64()?;
                 let b = this.read_scalar(b)?.to_f64()?;
@@ -373,7 +293,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[a, b, c]);
                 this.write_scalar(res, dest)?;
             }
-
             "fmaf64" => {
                 let [a, b, c] = check_arg_count(args)?;
                 let a = this.read_scalar(a)?.to_f64()?;
@@ -394,7 +313,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[f1, f2]);
                 this.write_scalar(res, dest)?;
             }
-
             "powf64" => {
                 let [f1, f2] = check_arg_count(args)?;
                 let f1 = this.read_scalar(f1)?.to_f64()?;
@@ -414,7 +332,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let res = this.adjust_nan(res, &[f]);
                 this.write_scalar(res, dest)?;
             }
-
             "powif64" => {
                 let [f, i] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
@@ -425,6 +342,79 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(res, dest)?;
             }
 
+            #[rustfmt::skip]
+            | "fadd_algebraic"
+            | "fsub_algebraic"
+            | "fmul_algebraic"
+            | "fdiv_algebraic"
+            | "frem_algebraic"
+            => {
+                let [a, b] = check_arg_count(args)?;
+                let a = this.read_immediate(a)?;
+                let b = this.read_immediate(b)?;
+                let op = match intrinsic_name {
+                    "fadd_algebraic" => mir::BinOp::Add,
+                    "fsub_algebraic" => mir::BinOp::Sub,
+                    "fmul_algebraic" => mir::BinOp::Mul,
+                    "fdiv_algebraic" => mir::BinOp::Div,
+                    "frem_algebraic" => mir::BinOp::Rem,
+                    _ => bug!(),
+                };
+                let res = this.wrapping_binary_op(op, &a, &b)?;
+                // `wrapping_binary_op` already called `generate_nan` if necessary.
+                this.write_immediate(*res, dest)?;
+            }
+
+            #[rustfmt::skip]
+            | "fadd_fast"
+            | "fsub_fast"
+            | "fmul_fast"
+            | "fdiv_fast"
+            | "frem_fast"
+            => {
+                let [a, b] = check_arg_count(args)?;
+                let a = this.read_immediate(a)?;
+                let b = this.read_immediate(b)?;
+                let op = match intrinsic_name {
+                    "fadd_fast" => mir::BinOp::Add,
+                    "fsub_fast" => mir::BinOp::Sub,
+                    "fmul_fast" => mir::BinOp::Mul,
+                    "fdiv_fast" => mir::BinOp::Div,
+                    "frem_fast" => mir::BinOp::Rem,
+                    _ => bug!(),
+                };
+                let float_finite = |x: &ImmTy<'tcx, _>| -> InterpResult<'tcx, bool> {
+                    let ty::Float(fty) = x.layout.ty.kind() else {
+                        bug!("float_finite: non-float input type {}", x.layout.ty)
+                    };
+                    Ok(match fty {
+                        FloatTy::F16 => unimplemented!("f16_f128"),
+                        FloatTy::F32 => x.to_scalar().to_f32()?.is_finite(),
+                        FloatTy::F64 => x.to_scalar().to_f64()?.is_finite(),
+                        FloatTy::F128 => unimplemented!("f16_f128"),
+                    })
+                };
+                match (float_finite(&a)?, float_finite(&b)?) {
+                    (false, false) => throw_ub_format!(
+                        "`{intrinsic_name}` intrinsic called with non-finite value as both parameters",
+                    ),
+                    (false, _) => throw_ub_format!(
+                        "`{intrinsic_name}` intrinsic called with non-finite value as first parameter",
+                    ),
+                    (_, false) => throw_ub_format!(
+                        "`{intrinsic_name}` intrinsic called with non-finite value as second parameter",
+                    ),
+                    _ => {}
+                }
+                let res = this.wrapping_binary_op(op, &a, &b)?;
+                if !float_finite(&res)? {
+                    throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result");
+                }
+                // This cannot be a NaN so we also don't have to apply any non-determinism.
+                // (Also, `wrapping_binary_op` already called `generate_nan` if needed.)
+                this.write_immediate(*res, dest)?;
+            }
+
             "float_to_int_unchecked" => {
                 let [val] = check_arg_count(args)?;
                 let val = this.read_immediate(val)?;