From 9907ad6ed9fde5ccdb58a7d59d652a4c8a98a346 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 17 Apr 2020 21:42:22 -0400 Subject: [PATCH] Define UB in float-to-int casts to saturate - Round to zero, and representable values cast directly. - `NaN` goes to 0 - Values beyond the limits of the type are saturated to the "nearest value" (essentially rounding to zero, in some sense) in the integral type, so e.g. `f32::INFINITY` would go to `{u,i}N::MAX.` --- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_interface/tests.rs | 2 +- src/librustc_session/options.rs | 4 ++-- src/test/codegen/unchecked-float-casts.rs | 12 ++++++------ .../ui/numbers-arithmetic/saturating-float-casts.rs | 1 - 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 19a0138d9cb..bb532abd84b 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -768,7 +768,7 @@ fn cast_float_to_int<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( ) -> Bx::Value { let fptosui_result = if signed { bx.fptosi(x, int_ty) } else { bx.fptoui(x, int_ty) }; - if !bx.cx().sess().opts.debugging_opts.saturating_float_casts { + if let Some(false) = bx.cx().sess().opts.debugging_opts.saturating_float_casts { return fptosui_result; } diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 0a200426e38..ad1934c9786 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -558,7 +558,7 @@ fn test_debugging_options_tracking_hash() { tracked!(sanitizer, Some(Sanitizer::Address)); tracked!(sanitizer_memory_track_origins, 2); tracked!(sanitizer_recover, vec![Sanitizer::Address]); - tracked!(saturating_float_casts, true); + tracked!(saturating_float_casts, Some(true)); tracked!(share_generics, Some(true)); tracked!(show_span, Some(String::from("abc"))); tracked!(src_hash_algorithm, Some(SourceFileHashAlgorithm::Sha1)); diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index b03fc00d93d..7fcf6d13850 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -936,9 +936,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "enable origins tracking in MemorySanitizer"), sanitizer_recover: Vec = (vec![], parse_sanitizer_list, [TRACKED], "enable recovery for selected sanitizers"), - saturating_float_casts: bool = (false, parse_bool, [TRACKED], + saturating_float_casts: Option = (None, parse_opt_bool, [TRACKED], "make float->int casts UB-free: numbers outside the integer type's range are clipped to \ - the max/min integer respectively, and NaN is mapped to 0 (default: no)"), + the max/min integer respectively, and NaN is mapped to 0 (default: yes)"), save_analysis: bool = (false, parse_bool, [UNTRACKED], "write syntax and type analysis (in JSON format) information, in \ addition to normal output (default: no)"), diff --git a/src/test/codegen/unchecked-float-casts.rs b/src/test/codegen/unchecked-float-casts.rs index 34e96122223..789feea12d6 100644 --- a/src/test/codegen/unchecked-float-casts.rs +++ b/src/test/codegen/unchecked-float-casts.rs @@ -1,7 +1,7 @@ -// compile-flags: -C no-prepopulate-passes +// This file tests that we don't generate any code for saturation when using the +// unchecked intrinsics. -// This file tests that we don't generate any code for saturation if -// -Z saturating-float-casts is not enabled. +// compile-flags: -C opt-level=3 #![crate_type = "lib"] @@ -12,7 +12,7 @@ pub fn f32_to_u32(x: f32) -> u32 { // CHECK-NOT: fcmp // CHECK-NOT: icmp // CHECK-NOT: select - x as u32 + unsafe { x.to_int_unchecked() } } // CHECK-LABEL: @f32_to_i32 @@ -22,7 +22,7 @@ pub fn f32_to_i32(x: f32) -> i32 { // CHECK-NOT: fcmp // CHECK-NOT: icmp // CHECK-NOT: select - x as i32 + unsafe { x.to_int_unchecked() } } #[no_mangle] @@ -31,5 +31,5 @@ pub fn f64_to_u16(x: f64) -> u16 { // CHECK-NOT: fcmp // CHECK-NOT: icmp // CHECK-NOT: select - x as u16 + unsafe { x.to_int_unchecked() } } diff --git a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs index f13964fb386..811efaefbb5 100644 --- a/src/test/ui/numbers-arithmetic/saturating-float-casts.rs +++ b/src/test/ui/numbers-arithmetic/saturating-float-casts.rs @@ -1,6 +1,5 @@ // run-pass // Tests saturating float->int casts. See u128-as-f32.rs for the opposite direction. -// compile-flags: -Z saturating-float-casts #![feature(test, stmt_expr_attributes)] #![deny(overflowing_literals)]