@@ -915,31 +915,48 @@ fn find_closure_call_expr(instance: &Instance, gcx: &mut GotocCtx, loc: Location
915915/// `align_offset`'s documentation, which states: "It is permissible for the implementation to 
916916/// always return usize::MAX. Only your algorithm’s performance can depend on getting a usable 
917917/// offset here, not its correctness." 
918- pub   struct  AlignOffset ; 
918+ struct  AlignOffset ; 
919919
920- impl < ' tcx >  GotocHook < ' tcx >  for  AlignOffset  { 
921-     fn  hook_applies ( & self ,  tcx :  TyCtxt < ' tcx > ,  instance :  Instance < ' tcx > )  -> bool  { 
922-         let  name  = with_no_trimmed_paths ! ( tcx . def_path_str ( instance. def_id ( ) ) ) ; 
923-         name ==  "std::ptr::align_offset"  
920+ impl  GotocHook  for  AlignOffset  { 
921+     fn  hook_applies ( & self ,  _tcx :  TyCtxt ,  instance :  Instance )  -> bool  { 
922+         let  full_name  = instance. name ( ) ; 
923+         full_name . starts_with ( "std::ptr::align_offset::<"  ) 
924924    } 
925925
926926    fn  handle ( 
927927        & self , 
928-         tcx :  & mut  GotocCtx < ' tcx > , 
929-         _instance :  Instance < ' tcx > , 
930-         mut  _fargs :  Vec < Expr > , 
931-         assign_to :  Place < ' tcx > , 
932-         target :  Option < BasicBlock > , 
933-         span :  Option < Span > , 
928+         gcx :  & mut  GotocCtx , 
929+         _instance :  Instance , 
930+         mut  fargs :  Vec < Expr > , 
931+         assign_to :  & Place , 
932+         target :  Option < BasicBlockIdx > , 
933+         span :  Span , 
934934    )  -> Stmt  { 
935-         let  loc = tcx. codegen_span_option ( span) ; 
936-         let  target = target. unwrap ( ) ; 
937-         let  place_expr =
938-             unwrap_or_return_codegen_unimplemented_stmt ! ( tcx,  tcx. codegen_place( & assign_to) ) 
939-                 . goto_expr ; 
935+         assert_eq ! ( fargs. len( ) ,  2 ) ; 
936+         let  _ptr = fargs. remove ( 0 ) ; 
937+         let  align = fargs. remove ( 0 ) ; 
938+         // test power-of-two: align > 0 && (align & (align - 1)) == 0 
939+         let  zero = Expr :: int_constant ( 0 ,  align. typ ( ) . clone ( ) ) ; 
940+         let  one = Expr :: int_constant ( 1 ,  align. typ ( ) . clone ( ) ) ; 
941+         let  cond = align
942+             . clone ( ) 
943+             . gt ( zero. clone ( ) ) 
944+             . and ( align. clone ( ) . bitand ( align. clone ( ) . sub ( one) ) . eq ( zero) ) ; 
945+         let  loc = gcx. codegen_span_stable ( span) ; 
946+         let  safety_check = gcx. codegen_assert_assume ( 
947+             cond, 
948+             PropertyClass :: SafetyCheck , 
949+             "align_offset: align is not a power-of-two" , 
950+             loc, 
951+         ) ; 
952+         let  place_expr = unwrap_or_return_codegen_unimplemented_stmt ! ( 
953+             gcx, 
954+             gcx. codegen_place_stable( & assign_to,  loc) 
955+         ) 
956+         . goto_expr ; 
940957        let  rhs = Expr :: int_constant ( usize:: MAX ,  place_expr. typ ( ) . clone ( ) ) ; 
941-         let  code  = place_expr. assign ( rhs,  loc) . with_location ( loc) ; 
942-         Stmt :: block ( vec ! [ code ,   Stmt :: goto( tcx . current_fn ( ) . find_label ( & target ) ,  loc) ] ,  loc) 
958+         let  assign  = place_expr. assign ( rhs,  loc) . with_location ( loc) ; 
959+         Stmt :: block ( vec ! [ safety_check ,  assign ,   Stmt :: goto( bb_label ( target . unwrap ( ) ) ,  loc) ] ,  loc) 
943960    } 
944961} 
945962
0 commit comments