@@ -384,6 +384,14 @@ impl GotocCtx<'_> {
384
384
let binop_stmt = codegen_intrinsic_binop ! ( div) ;
385
385
self . add_finite_args_checks ( intrinsic_str, fargs_clone, binop_stmt, span)
386
386
}
387
+ Intrinsic :: FloatToIntUnchecked => self . codegen_float_to_int_unchecked (
388
+ intrinsic_str,
389
+ fargs. remove ( 0 ) ,
390
+ farg_types[ 0 ] ,
391
+ place,
392
+ ret_ty,
393
+ loc,
394
+ ) ,
387
395
Intrinsic :: FloorF32 => codegen_simple_intrinsic ! ( Floorf ) ,
388
396
Intrinsic :: FloorF64 => codegen_simple_intrinsic ! ( Floor ) ,
389
397
Intrinsic :: FmafF32 => codegen_simple_intrinsic ! ( Fmaf ) ,
@@ -1917,6 +1925,57 @@ impl GotocCtx<'_> {
1917
1925
Stmt :: block ( vec ! [ non_overlapping_stmt, assign_to_t, assign_to_y, assign_to_x] , loc)
1918
1926
}
1919
1927
}
1928
+
1929
+ /// Checks that the floating-point value is:
1930
+ /// 1. Finite (i.e. neither infinite nor NaN)
1931
+ /// 2. Its truncated value is in range of the target integer
1932
+ /// then performs the cast to the target type
1933
+ pub fn codegen_float_to_int_unchecked (
1934
+ & mut self ,
1935
+ intrinsic : & str ,
1936
+ expr : Expr ,
1937
+ ty : Ty ,
1938
+ place : & Place ,
1939
+ res_ty : Ty ,
1940
+ loc : Location ,
1941
+ ) -> Stmt {
1942
+ let finite_check = self . codegen_assert_assume (
1943
+ expr. clone ( ) . is_finite ( ) ,
1944
+ PropertyClass :: ArithmeticOverflow ,
1945
+ format ! ( "{intrinsic}: attempt to convert a non-finite value to an integer" ) . as_str ( ) ,
1946
+ loc,
1947
+ ) ;
1948
+
1949
+ assert ! ( res_ty. kind( ) . is_integral( ) ) ;
1950
+ assert ! ( ty. kind( ) . is_float( ) ) ;
1951
+ let TyKind :: RigidTy ( integral_ty) = res_ty. kind ( ) else {
1952
+ panic ! (
1953
+ "Expected intrinsic `{}` type to be `RigidTy`, but found: `{:?}`" ,
1954
+ intrinsic, res_ty
1955
+ ) ;
1956
+ } ;
1957
+ let TyKind :: RigidTy ( RigidTy :: Float ( float_type) ) = ty. kind ( ) else {
1958
+ panic ! ( "Expected intrinsic `{}` type to be `Float`, but found: `{:?}`" , intrinsic, ty) ;
1959
+ } ;
1960
+ let mm = self . symbol_table . machine_model ( ) ;
1961
+ let in_range = utils:: codegen_in_range_expr ( & expr, float_type, integral_ty, mm) ;
1962
+
1963
+ let range_check = self . codegen_assert_assume (
1964
+ in_range,
1965
+ PropertyClass :: ArithmeticOverflow ,
1966
+ format ! ( "{intrinsic}: attempt to convert a value out of range of the target integer" )
1967
+ . as_str ( ) ,
1968
+ loc,
1969
+ ) ;
1970
+
1971
+ let int_type = self . codegen_ty_stable ( res_ty) ;
1972
+ let cast = expr. cast_to ( int_type) ;
1973
+
1974
+ Stmt :: block (
1975
+ vec ! [ finite_check, range_check, self . codegen_expr_to_place_stable( place, cast, loc) ] ,
1976
+ loc,
1977
+ )
1978
+ }
1920
1979
}
1921
1980
1922
1981
fn instance_args ( instance : & Instance ) -> GenericArgs {
0 commit comments