88//! It would be too nasty if we spread around these sort of undocumented hooks in place, so
99//! this module addresses this issue.
1010
11- use crate :: codegen_cprover_gotoc:: GotocCtx ;
1211use crate :: codegen_cprover_gotoc:: codegen:: { PropertyClass , bb_label} ;
12+ use crate :: codegen_cprover_gotoc:: { GotocCtx , utils} ;
1313use crate :: kani_middle:: attributes;
1414use crate :: kani_middle:: kani_functions:: { KaniFunction , KaniHook } ;
1515use crate :: unwrap_or_return_codegen_unimplemented_stmt;
@@ -19,6 +19,7 @@ use rustc_middle::ty::TyCtxt;
1919use rustc_smir:: rustc_internal;
2020use stable_mir:: mir:: mono:: Instance ;
2121use stable_mir:: mir:: { BasicBlockIdx , Place } ;
22+ use stable_mir:: ty:: RigidTy ;
2223use stable_mir:: { CrateDef , ty:: Span } ;
2324use std:: collections:: HashMap ;
2425use std:: rc:: Rc ;
@@ -315,6 +316,54 @@ impl GotocHook for IsAllocated {
315316 }
316317}
317318
319+ /// This is the hook for the `kani::float::float_to_int_in_range` intrinsic
320+ /// TODO: This should be replaced by a Rust function instead so that it's
321+ /// independent of the backend
322+ struct FloatToIntInRange ;
323+ impl GotocHook for FloatToIntInRange {
324+ fn hook_applies ( & self , _tcx : TyCtxt , _instance : Instance ) -> bool {
325+ unreachable ! ( "{UNEXPECTED_CALL}" )
326+ }
327+
328+ fn handle (
329+ & self ,
330+ gcx : & mut GotocCtx ,
331+ instance : Instance ,
332+ mut fargs : Vec < Expr > ,
333+ assign_to : & Place ,
334+ target : Option < BasicBlockIdx > ,
335+ span : Span ,
336+ ) -> Stmt {
337+ assert_eq ! ( fargs. len( ) , 1 ) ;
338+ let float = fargs. remove ( 0 ) ;
339+ let target = target. unwrap ( ) ;
340+ let loc = gcx. codegen_span_stable ( span) ;
341+
342+ let generic_args = instance. args ( ) . 0 ;
343+ let RigidTy :: Float ( float_ty) = generic_args[ 0 ] . expect_ty ( ) . kind ( ) . rigid ( ) . unwrap ( ) . clone ( )
344+ else {
345+ unreachable ! ( )
346+ } ;
347+ let integral_ty = generic_args[ 1 ] . expect_ty ( ) . kind ( ) . rigid ( ) . unwrap ( ) . clone ( ) ;
348+
349+ let is_in_range = utils:: codegen_in_range_expr (
350+ & float,
351+ float_ty,
352+ integral_ty,
353+ gcx. symbol_table . machine_model ( ) ,
354+ )
355+ . cast_to ( Type :: CInteger ( CIntType :: Bool ) ) ;
356+
357+ let pe = unwrap_or_return_codegen_unimplemented_stmt ! (
358+ gcx,
359+ gcx. codegen_place_stable( assign_to, loc)
360+ )
361+ . goto_expr ;
362+
363+ Stmt :: block ( vec ! [ pe. assign( is_in_range, loc) , Stmt :: goto( bb_label( target) , loc) ] , loc)
364+ }
365+ }
366+
318367/// Encodes __CPROVER_pointer_object(ptr)
319368struct PointerObject ;
320369impl GotocHook for PointerObject {
@@ -663,6 +712,7 @@ pub fn fn_hooks() -> GotocHooks {
663712 ( KaniHook :: PointerOffset , Rc :: new ( PointerOffset ) ) ,
664713 ( KaniHook :: UntrackedDeref , Rc :: new ( UntrackedDeref ) ) ,
665714 ( KaniHook :: InitContracts , Rc :: new ( InitContracts ) ) ,
715+ ( KaniHook :: FloatToIntInRange , Rc :: new ( FloatToIntInRange ) ) ,
666716 ] ;
667717 GotocHooks {
668718 kani_lib_hooks : HashMap :: from ( kani_lib_hooks) ,
0 commit comments