From 6eab94a459a16a4da0c6e18583bf70ee8c42cb1f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Jun 2019 00:12:57 +0200 Subject: [PATCH 1/6] fix from to/from f32/f64 changes --- src/fn_call.rs | 4 ++-- src/intrinsic.rs | 40 ++++++++++++++++++++++++---------------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index e9377d89bca..3d2c523bf70 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -758,7 +758,7 @@ fn emulate_foreign_item( this.machine.last_error = err; } "GetLastError" => { - this.write_scalar(Scalar::from_uint(this.machine.last_error, Size::from_bits(32)), dest)?; + this.write_scalar(Scalar::from_u32(this.machine.last_error), dest)?; } "AddVectoredExceptionHandler" => { @@ -854,7 +854,7 @@ fn emulate_foreign_item( }; // If there was no error, write back how much was written. if let Some(n) = written { - this.write_scalar(Scalar::from_uint(n, Size::from_bits(32)), written_place.into())?; + this.write_scalar(Scalar::from_u32(n), written_place.into())?; } // Return whether this was a success. this.write_scalar( diff --git a/src/intrinsic.rs b/src/intrinsic.rs index 822265bc211..faaa15d3ba9 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -186,7 +186,8 @@ fn call_intrinsic( "sinf32" | "fabsf32" | "cosf32" | "sqrtf32" | "expf32" | "exp2f32" | "logf32" | "log10f32" | "log2f32" | "floorf32" | "ceilf32" | "truncf32" => { - let f = this.read_scalar(args[0])?.to_f32()?; + // FIXME: Using host floats. + let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?); let f = match intrinsic_name.get() { "sinf32" => f.sin(), "fabsf32" => f.abs(), @@ -202,12 +203,13 @@ fn call_intrinsic( "truncf32" => f.trunc(), _ => bug!(), }; - this.write_scalar(Scalar::from_f32(f), dest)?; + this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?; } "sinf64" | "fabsf64" | "cosf64" | "sqrtf64" | "expf64" | "exp2f64" | "logf64" | "log10f64" | "log2f64" | "floorf64" | "ceilf64" | "truncf64" => { - let f = this.read_scalar(args[0])?.to_f64()?; + // FIXME: Using host floats. + let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?); let f = match intrinsic_name.get() { "sinf64" => f.sin(), "fabsf64" => f.abs(), @@ -223,7 +225,7 @@ fn call_intrinsic( "truncf64" => f.trunc(), _ => bug!(), }; - this.write_scalar(Scalar::from_f64(f), dest)?; + this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?; } "fadd_fast" | "fsub_fast" | "fmul_fast" | "fdiv_fast" | "frem_fast" => { @@ -320,19 +322,21 @@ fn call_intrinsic( } "powf32" => { - let f = this.read_scalar(args[0])?.to_f32()?; - let f2 = this.read_scalar(args[1])?.to_f32()?; + // FIXME: Using host floats. + let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?); + let f2 = f32::from_bits(this.read_scalar(args[1])?.to_u32()?); this.write_scalar( - Scalar::from_f32(f.powf(f2)), + Scalar::from_u32(f.powf(f2).to_bits()), dest, )?; } "powf64" => { - let f = this.read_scalar(args[0])?.to_f64()?; - let f2 = this.read_scalar(args[1])?.to_f64()?; + // FIXME: Using host floats. + let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?); + let f2 = f64::from_bits(this.read_scalar(args[1])?.to_u64()?); this.write_scalar( - Scalar::from_f64(f.powf(f2)), + Scalar::from_u64(f.powf(f2).to_bits()), dest, )?; } @@ -341,8 +345,9 @@ fn call_intrinsic( let a = this.read_scalar(args[0])?.to_f32()?; let b = this.read_scalar(args[1])?.to_f32()?; let c = this.read_scalar(args[2])?.to_f32()?; + let res = (a*b).value + c; this.write_scalar( - Scalar::from_f32(a * b + c), + Scalar::from_f32(res.value), dest, )?; } @@ -351,26 +356,29 @@ fn call_intrinsic( let a = this.read_scalar(args[0])?.to_f64()?; let b = this.read_scalar(args[1])?.to_f64()?; let c = this.read_scalar(args[2])?.to_f64()?; + let res = (a*b).value + c; this.write_scalar( - Scalar::from_f64(a * b + c), + Scalar::from_f64(res.value), dest, )?; } "powif32" => { - let f = this.read_scalar(args[0])?.to_f32()?; + // FIXME: Using host floats. + let f = f32::from_bits(this.read_scalar(args[0])?.to_u32()?); let i = this.read_scalar(args[1])?.to_i32()?; this.write_scalar( - Scalar::from_f32(f.powi(i)), + Scalar::from_u32(f.powi(i).to_bits()), dest, )?; } "powif64" => { - let f = this.read_scalar(args[0])?.to_f64()?; + // FIXME: Using host floats. + let f = f64::from_bits(this.read_scalar(args[0])?.to_u64()?); let i = this.read_scalar(args[1])?.to_i32()?; this.write_scalar( - Scalar::from_f64(f.powi(i)), + Scalar::from_u64(f.powi(i).to_bits()), dest, )?; } From 5e07ac335fe75aafd34394ff95bb2f153c11c967 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Jun 2019 00:19:05 +0200 Subject: [PATCH 2/6] implement min and max floating point intrinsics --- src/intrinsic.rs | 23 +++++++++++++++++++++++ src/lib.rs | 4 ++-- tests/run-pass/floats.rs | 15 ++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/intrinsic.rs b/src/intrinsic.rs index faaa15d3ba9..a28c99db6bf 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -1,3 +1,4 @@ +use rustc_apfloat::Float; use rustc::mir; use rustc::mir::interpret::{InterpResult, PointerArithmetic}; use rustc::ty::layout::{self, LayoutOf, Size}; @@ -242,6 +243,28 @@ fn call_intrinsic( this.binop_ignore_overflow(op, a, b, dest)?; } + "minnumf32" | "maxnumf32" => { + let a = this.read_scalar(args[0])?.to_f32()?; + let b = this.read_scalar(args[1])?.to_f32()?; + let res = if intrinsic_name.get().starts_with("min") { + a.min(b) + } else { + a.max(b) + }; + this.write_scalar(Scalar::from_f32(res), dest)?; + } + + "minnumf64" | "maxnumf64" => { + let a = this.read_scalar(args[0])?.to_f64()?; + let b = this.read_scalar(args[1])?.to_f64()?; + let res = if intrinsic_name.get().starts_with("min") { + a.min(b) + } else { + a.max(b) + }; + this.write_scalar(Scalar::from_f64(res), dest)?; + } + "exact_div" => { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1` diff --git a/src/lib.rs b/src/lib.rs index d0b7111bb06..d2b20db06d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,8 +6,8 @@ extern crate log; // From rustc. extern crate syntax; -#[macro_use] -extern crate rustc; +extern crate rustc_apfloat; +#[macro_use] extern crate rustc; extern crate rustc_data_structures; extern crate rustc_mir; extern crate rustc_target; diff --git a/tests/run-pass/floats.rs b/tests/run-pass/floats.rs index 39fdbce4920..c1588dae249 100644 --- a/tests/run-pass/floats.rs +++ b/tests/run-pass/floats.rs @@ -1,4 +1,3 @@ - fn main() { assert_eq!(6.0_f32*6.0_f32, 36.0_f32); assert_eq!(6.0_f64*6.0_f64, 36.0_f64); @@ -12,4 +11,18 @@ fn main() { assert_eq!(5.0f32 as u32, 5); assert_eq!(5.0f32 as i32, 5); assert_eq!(-5.0f32 as i32, -5); + + assert_eq!((1.0 as f32).max(-1.0), 1.0); + assert_eq!((1.0 as f32).min(-1.0), -1.0); + assert_eq!(std::f32::NAN.min(9.0), 9.0); + assert_eq!(std::f32::NAN.max(-9.0), -9.0); + assert_eq!((9.0 as f32).min(std::f32::NAN), 9.0); + assert_eq!((-9.0 as f32).max(std::f32::NAN), -9.0); + + assert_eq!((1.0 as f64).max(-1.0), 1.0); + assert_eq!((1.0 as f64).min(-1.0), -1.0); + assert_eq!(std::f64::NAN.min(9.0), 9.0); + assert_eq!(std::f64::NAN.max(-9.0), -9.0); + assert_eq!((9.0 as f64).min(std::f64::NAN), 9.0); + assert_eq!((-9.0 as f64).max(std::f64::NAN), -9.0); } From a37953752d325e3a08ee7db27709a9d9c170b0ff Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Jun 2019 09:49:06 +0200 Subject: [PATCH 3/6] use apfloat's FMA primitive --- src/intrinsic.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/intrinsic.rs b/src/intrinsic.rs index a28c99db6bf..451a97eeed7 100644 --- a/src/intrinsic.rs +++ b/src/intrinsic.rs @@ -368,9 +368,9 @@ fn call_intrinsic( let a = this.read_scalar(args[0])?.to_f32()?; let b = this.read_scalar(args[1])?.to_f32()?; let c = this.read_scalar(args[2])?.to_f32()?; - let res = (a*b).value + c; + let res = a.mul_add(b, c).value; this.write_scalar( - Scalar::from_f32(res.value), + Scalar::from_f32(res), dest, )?; } @@ -379,9 +379,9 @@ fn call_intrinsic( let a = this.read_scalar(args[0])?.to_f64()?; let b = this.read_scalar(args[1])?.to_f64()?; let c = this.read_scalar(args[2])?.to_f64()?; - let res = (a*b).value + c; + let res = a.mul_add(b, c).value; this.write_scalar( - Scalar::from_f64(res.value), + Scalar::from_f64(res), dest, )?; } From 9c9a947bf4b90623a9db50c9349808b45ca2fc11 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Jun 2019 09:50:47 +0200 Subject: [PATCH 4/6] test more enum-int-cast code paths --- tests/run-pass/c_enums.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/run-pass/c_enums.rs b/tests/run-pass/c_enums.rs index 11897b73eb2..16b795342ea 100644 --- a/tests/run-pass/c_enums.rs +++ b/tests/run-pass/c_enums.rs @@ -11,11 +11,13 @@ enum Signed { } fn foo() -> [u8; 3] { - [Foo::Bar as u8, Foo::Baz as u8, Foo::Quux as u8] + let baz = Foo::Baz; // let-expansion changes the MIR significantly + [Foo::Bar as u8, baz as u8, Foo::Quux as u8] } fn signed() -> [i8; 3] { - [Signed::Bar as i8, Signed::Baz as i8, Signed::Quux as i8] + let baz = Signed::Baz; // let-expansion changes the MIR significantly + [Signed::Bar as i8, baz as i8, Signed::Quux as i8] } fn unsafe_match() -> bool { From e2f114a5e071a1785024fdaf6260b656b226a696 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Jun 2019 09:57:01 +0200 Subject: [PATCH 5/6] test FMA a bit more --- tests/run-pass/intrinsics-math.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/run-pass/intrinsics-math.rs b/tests/run-pass/intrinsics-math.rs index a2c55634749..6b3d15a5091 100644 --- a/tests/run-pass/intrinsics-math.rs +++ b/tests/run-pass/intrinsics-math.rs @@ -50,8 +50,10 @@ pub fn main() { assert_approx_eq!(8f32.log2(), 3f32); assert_approx_eq!(f64::consts::E.log2(), f64::consts::LOG2_E); - assert_approx_eq!(1.0f32.mul_add(2.0f32, 5.0f32), 7.0f32); - assert_approx_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); + assert_approx_eq!(3.0f32.mul_add(2.0f32, 5.0f32), 11.0); + assert_eq!(0.0f32.mul_add(-2.0, f32::consts::E), f32::consts::E); + assert_approx_eq!(3.0f64.mul_add(2.0, 5.0), 11.0); + assert_eq!(0.0f64.mul_add(-2.0f64, f64::consts::E), f64::consts::E); assert_approx_eq!((-1.0f32).abs(), 1.0f32); assert_approx_eq!(34.2f64.abs(), 34.2f64); From 6a0d092eaf3150a4ae2e509744c49d5cadc60efc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 11 Jun 2019 19:42:01 +0200 Subject: [PATCH 6/6] bump Rust version --- rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-version b/rust-version index b72e1f53ef1..8ef35afca05 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -1cbd8a4d686d1411105f26cddf876c5994e69593 +8e948df707ea8a3c88c65bf2ffdcb2f1cf5491be