8
8
//! It would be too nasty if we spread around these sort of undocumented hooks in place, so
9
9
//! this module addresses this issue.
10
10
11
- use crate :: codegen_cprover_gotoc:: GotocCtx ;
12
11
use crate :: codegen_cprover_gotoc:: codegen:: { PropertyClass , bb_label} ;
12
+ use crate :: codegen_cprover_gotoc:: { GotocCtx , utils} ;
13
13
use crate :: kani_middle:: attributes;
14
14
use crate :: kani_middle:: kani_functions:: { KaniFunction , KaniHook } ;
15
15
use crate :: unwrap_or_return_codegen_unimplemented_stmt;
@@ -19,6 +19,7 @@ use rustc_middle::ty::TyCtxt;
19
19
use rustc_smir:: rustc_internal;
20
20
use stable_mir:: mir:: mono:: Instance ;
21
21
use stable_mir:: mir:: { BasicBlockIdx , Place } ;
22
+ use stable_mir:: ty:: RigidTy ;
22
23
use stable_mir:: { CrateDef , ty:: Span } ;
23
24
use std:: collections:: HashMap ;
24
25
use std:: rc:: Rc ;
@@ -315,6 +316,53 @@ impl GotocHook for IsAllocated {
315
316
}
316
317
}
317
318
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 ( ) else {
344
+ unreachable ! ( )
345
+ } ;
346
+ let integral_ty = generic_args[ 1 ] . expect_ty ( ) . kind ( ) . rigid ( ) . unwrap ( ) . clone ( ) ;
347
+
348
+ let is_in_range = utils:: codegen_in_range_expr (
349
+ & float,
350
+ float_ty,
351
+ integral_ty,
352
+ gcx. symbol_table . machine_model ( ) ,
353
+ )
354
+ . cast_to ( Type :: CInteger ( CIntType :: Bool ) ) ;
355
+
356
+ let pe = unwrap_or_return_codegen_unimplemented_stmt ! (
357
+ gcx,
358
+ gcx. codegen_place_stable( assign_to, loc)
359
+ )
360
+ . goto_expr ;
361
+
362
+ Stmt :: block ( vec ! [ pe. assign( is_in_range, loc) , Stmt :: goto( bb_label( target) , loc) ] , loc)
363
+ }
364
+ }
365
+
318
366
/// Encodes __CPROVER_pointer_object(ptr)
319
367
struct PointerObject ;
320
368
impl GotocHook for PointerObject {
@@ -663,6 +711,7 @@ pub fn fn_hooks() -> GotocHooks {
663
711
( KaniHook :: PointerOffset , Rc :: new ( PointerOffset ) ) ,
664
712
( KaniHook :: UntrackedDeref , Rc :: new ( UntrackedDeref ) ) ,
665
713
( KaniHook :: InitContracts , Rc :: new ( InitContracts ) ) ,
714
+ ( KaniHook :: FloatToIntInRange , Rc :: new ( FloatToIntInRange ) ) ,
666
715
] ;
667
716
GotocHooks {
668
717
kani_lib_hooks : HashMap :: from ( kani_lib_hooks) ,
0 commit comments