diff --git a/rust-version b/rust-version index b72e1f53ef..8ef35afca0 100644 --- a/rust-version +++ b/rust-version @@ -1 +1 @@ -1cbd8a4d686d1411105f26cddf876c5994e69593 +8e948df707ea8a3c88c65bf2ffdcb2f1cf5491be diff --git a/src/fn_call.rs b/src/fn_call.rs index e9377d89bc..3d2c523bf7 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -758,7 +758,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' 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 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a + 'mir>: crate::MiriEvalContextExt<' }; // 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 822265bc21..451a97eeed 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}; @@ -186,7 +187,8 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, "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 +204,13 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, "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 +226,7 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, "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" => { @@ -240,6 +243,28 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 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` @@ -320,19 +345,21 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, } "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 +368,9 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 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.mul_add(b, c).value; this.write_scalar( - Scalar::from_f32(a * b + c), + Scalar::from_f32(res), dest, )?; } @@ -351,26 +379,29 @@ pub trait EvalContextExt<'a, 'mir, 'tcx: 'a+'mir>: crate::MiriEvalContextExt<'a, 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.mul_add(b, c).value; this.write_scalar( - Scalar::from_f64(a * b + c), + Scalar::from_f64(res), 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, )?; } diff --git a/src/lib.rs b/src/lib.rs index d0b7111bb0..d2b20db06d 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/c_enums.rs b/tests/run-pass/c_enums.rs index 11897b73eb..16b795342e 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 { diff --git a/tests/run-pass/floats.rs b/tests/run-pass/floats.rs index 39fdbce492..c1588dae24 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); } diff --git a/tests/run-pass/intrinsics-math.rs b/tests/run-pass/intrinsics-math.rs index a2c5563474..6b3d15a509 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);